160484Sobrien/* dwarf2dbg.c - DWARF2 debug support 2218822Sdim Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 3218822Sdim Free Software Foundation, Inc. 460484Sobrien Contributed by David Mosberger-Tang <davidm@hpl.hp.com> 560484Sobrien 660484Sobrien This file is part of GAS, the GNU Assembler. 760484Sobrien 860484Sobrien GAS is free software; you can redistribute it and/or modify 960484Sobrien it under the terms of the GNU General Public License as published by 1060484Sobrien the Free Software Foundation; either version 2, or (at your option) 1160484Sobrien any later version. 1260484Sobrien 1360484Sobrien GAS is distributed in the hope that it will be useful, 1460484Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 1560484Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1660484Sobrien GNU General Public License for more details. 1760484Sobrien 1860484Sobrien You should have received a copy of the GNU General Public License 1960484Sobrien along with GAS; see the file COPYING. If not, write to the Free 20218822Sdim Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 21218822Sdim 02110-1301, USA. */ 2260484Sobrien 2360484Sobrien/* Logical line numbers can be controlled by the compiler via the 24218822Sdim following directives: 2560484Sobrien 2660484Sobrien .file FILENO "file.c" 27218822Sdim .loc FILENO LINENO [COLUMN] [basic_block] [prologue_end] \ 28218822Sdim [epilogue_begin] [is_stmt VALUE] [isa VALUE] 29218822Sdim*/ 3060484Sobrien 3177298Sobrien#include "as.h" 32218822Sdim#include "safe-ctype.h" 3360484Sobrien 3477298Sobrien#ifdef HAVE_LIMITS_H 3577298Sobrien#include <limits.h> 3677298Sobrien#else 3777298Sobrien#ifdef HAVE_SYS_PARAM_H 3877298Sobrien#include <sys/param.h> 3977298Sobrien#endif 4077298Sobrien#ifndef INT_MAX 4177298Sobrien#define INT_MAX (int) (((unsigned) (-1)) >> 1) 4277298Sobrien#endif 4377298Sobrien#endif 4477298Sobrien 45130561Sobrien#include "dwarf2dbg.h" 46130561Sobrien#include <filenames.h> 47130561Sobrien 48218822Sdim#ifdef HAVE_DOS_BASED_FILE_SYSTEM 49218822Sdim/* We need to decide which character to use as a directory separator. 50218822Sdim Just because HAVE_DOS_BASED_FILE_SYSTEM is defined, it does not 51218822Sdim necessarily mean that the backslash character is the one to use. 52218822Sdim Some environments, eg Cygwin, can support both naming conventions. 53218822Sdim So we use the heuristic that we only need to use the backslash if 54218822Sdim the path is an absolute path starting with a DOS style drive 55218822Sdim selector. eg C: or D: */ 56218822Sdim# define INSERT_DIR_SEPARATOR(string, offset) \ 57218822Sdim do \ 58218822Sdim { \ 59218822Sdim if (offset > 1 \ 60218822Sdim && string[0] != 0 \ 61218822Sdim && string[1] == ':') \ 62218822Sdim string [offset] = '\\'; \ 63218822Sdim else \ 64218822Sdim string [offset] = '/'; \ 65218822Sdim } \ 66218822Sdim while (0) 67218822Sdim#else 68218822Sdim# define INSERT_DIR_SEPARATOR(string, offset) string[offset] = '/' 69218822Sdim#endif 70218822Sdim 71130561Sobrien#ifndef DWARF2_FORMAT 72130561Sobrien# define DWARF2_FORMAT() dwarf2_format_32bit 73130561Sobrien#endif 74130561Sobrien 75130561Sobrien#ifndef DWARF2_ADDR_SIZE 76130561Sobrien# define DWARF2_ADDR_SIZE(bfd) (bfd_arch_bits_per_address (bfd) / 8) 77130561Sobrien#endif 78130561Sobrien 7960484Sobrien#include "subsegs.h" 8060484Sobrien 8160484Sobrien#include "elf/dwarf2.h" 8260484Sobrien 8360484Sobrien/* Since we can't generate the prolog until the body is complete, we 8460484Sobrien use three different subsegments for .debug_line: one holding the 8560484Sobrien prolog, one for the directory and filename info, and one for the 8660484Sobrien body ("statement program"). */ 8760484Sobrien#define DL_PROLOG 0 8860484Sobrien#define DL_FILES 1 8960484Sobrien#define DL_BODY 2 9060484Sobrien 91218822Sdim/* If linker relaxation might change offsets in the code, the DWARF special 92218822Sdim opcodes and variable-length operands cannot be used. If this macro is 93218822Sdim nonzero, use the DW_LNS_fixed_advance_pc opcode instead. */ 94218822Sdim#ifndef DWARF2_USE_FIXED_ADVANCE_PC 95218822Sdim# define DWARF2_USE_FIXED_ADVANCE_PC 0 96218822Sdim#endif 97218822Sdim 9860484Sobrien/* First special line opcde - leave room for the standard opcodes. 9960484Sobrien Note: If you want to change this, you'll have to update the 10060484Sobrien "standard_opcode_lengths" table that is emitted below in 101218822Sdim out_debug_line(). */ 102218822Sdim#define DWARF2_LINE_OPCODE_BASE 13 10360484Sobrien 10460484Sobrien#ifndef DWARF2_LINE_BASE 10560484Sobrien /* Minimum line offset in a special line info. opcode. This value 10660484Sobrien was chosen to give a reasonable range of values. */ 10760484Sobrien# define DWARF2_LINE_BASE -5 10860484Sobrien#endif 10960484Sobrien 11060484Sobrien/* Range of line offsets in a special line info. opcode. */ 11160484Sobrien#ifndef DWARF2_LINE_RANGE 11260484Sobrien# define DWARF2_LINE_RANGE 14 11360484Sobrien#endif 11460484Sobrien 11560484Sobrien#ifndef DWARF2_LINE_MIN_INSN_LENGTH 11660484Sobrien /* Define the architecture-dependent minimum instruction length (in 11760484Sobrien bytes). This value should be rather too small than too big. */ 11877298Sobrien# define DWARF2_LINE_MIN_INSN_LENGTH 1 11960484Sobrien#endif 12060484Sobrien 121218822Sdim/* Flag that indicates the initial value of the is_stmt_start flag. */ 12260484Sobrien#define DWARF2_LINE_DEFAULT_IS_STMT 1 12360484Sobrien 12460484Sobrien/* Given a special op, return the line skip amount. */ 12560484Sobrien#define SPECIAL_LINE(op) \ 12660484Sobrien (((op) - DWARF2_LINE_OPCODE_BASE)%DWARF2_LINE_RANGE + DWARF2_LINE_BASE) 12760484Sobrien 12860484Sobrien/* Given a special op, return the address skip amount (in units of 12960484Sobrien DWARF2_LINE_MIN_INSN_LENGTH. */ 13060484Sobrien#define SPECIAL_ADDR(op) (((op) - DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE) 13160484Sobrien 13260484Sobrien/* The maximum address skip amount that can be encoded with a special op. */ 13360484Sobrien#define MAX_SPECIAL_ADDR_DELTA SPECIAL_ADDR(255) 13460484Sobrien 13577298Sobrienstruct line_entry { 13677298Sobrien struct line_entry *next; 137218822Sdim symbolS *label; 13877298Sobrien struct dwarf2_line_info loc; 13977298Sobrien}; 14060484Sobrien 14177298Sobrienstruct line_subseg { 14277298Sobrien struct line_subseg *next; 14377298Sobrien subsegT subseg; 14477298Sobrien struct line_entry *head; 14577298Sobrien struct line_entry **ptail; 14677298Sobrien}; 14760484Sobrien 14877298Sobrienstruct line_seg { 14977298Sobrien struct line_seg *next; 15077298Sobrien segT seg; 15177298Sobrien struct line_subseg *head; 15277298Sobrien symbolS *text_start; 15377298Sobrien symbolS *text_end; 15477298Sobrien}; 15560484Sobrien 15677298Sobrien/* Collects data for all line table entries during assembly. */ 15777298Sobrienstatic struct line_seg *all_segs; 15860484Sobrien 15977298Sobrienstruct file_entry { 160130561Sobrien const char *filename; 16177298Sobrien unsigned int dir; 16277298Sobrien}; 16360484Sobrien 16477298Sobrien/* Table of files used by .debug_line. */ 16577298Sobrienstatic struct file_entry *files; 16677298Sobrienstatic unsigned int files_in_use; 16777298Sobrienstatic unsigned int files_allocated; 16877298Sobrien 169130561Sobrien/* Table of directories used by .debug_line. */ 170130561Sobrienstatic char **dirs; 171130561Sobrienstatic unsigned int dirs_in_use; 172130561Sobrienstatic unsigned int dirs_allocated; 173130561Sobrien 174130561Sobrien/* TRUE when we've seen a .loc directive recently. Used to avoid 17577298Sobrien doing work when there's nothing to do. */ 176130561Sobrienstatic bfd_boolean loc_directive_seen; 17777298Sobrien 178218822Sdim/* TRUE when we're supposed to set the basic block mark whenever a 179218822Sdim label is seen. */ 180218822Sdimbfd_boolean dwarf2_loc_mark_labels; 181218822Sdim 18277298Sobrien/* Current location as indicated by the most recent .loc directive. */ 183218822Sdimstatic struct dwarf2_line_info current = { 184218822Sdim 1, 1, 0, 0, 185218822Sdim DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0 186218822Sdim}; 18777298Sobrien 18877298Sobrien/* The size of an address on the target. */ 18977298Sobrienstatic unsigned int sizeof_address; 19077298Sobrien 191130561Sobrienstatic struct line_subseg *get_line_subseg (segT, subsegT); 192130561Sobrienstatic unsigned int get_filenum (const char *, unsigned int); 193130561Sobrienstatic struct frag *first_frag_for_seg (segT); 194130561Sobrienstatic struct frag *last_frag_for_seg (segT); 195130561Sobrienstatic void out_byte (int); 196130561Sobrienstatic void out_opcode (int); 197130561Sobrienstatic void out_two (int); 198130561Sobrienstatic void out_four (int); 199130561Sobrienstatic void out_abbrev (int, int); 200130561Sobrienstatic void out_uleb128 (addressT); 201218822Sdimstatic void out_sleb128 (addressT); 202218822Sdimstatic offsetT get_frag_fix (fragS *, segT); 203218822Sdimstatic void out_set_addr (symbolS *); 204130561Sobrienstatic int size_inc_line_addr (int, addressT); 205130561Sobrienstatic void emit_inc_line_addr (int, addressT, char *, int); 206130561Sobrienstatic void out_inc_line_addr (int, addressT); 207218822Sdimstatic void out_fixed_inc_line_addr (int, symbolS *, symbolS *); 208218822Sdimstatic void relax_inc_line_addr (int, symbolS *, symbolS *); 209130561Sobrienstatic void process_entries (segT, struct line_entry *); 210130561Sobrienstatic void out_file_list (void); 211130561Sobrienstatic void out_debug_line (segT); 212130561Sobrienstatic void out_debug_aranges (segT, segT); 213130561Sobrienstatic void out_debug_abbrev (segT); 21477298Sobrien 215130561Sobrien#ifndef TC_DWARF2_EMIT_OFFSET 216218822Sdim#define TC_DWARF2_EMIT_OFFSET generic_dwarf2_emit_offset 217130561Sobrien 218130561Sobrien/* Create an offset to .dwarf2_*. */ 219130561Sobrien 220130561Sobrienstatic void 221130561Sobriengeneric_dwarf2_emit_offset (symbolS *symbol, unsigned int size) 222130561Sobrien{ 223130561Sobrien expressionS expr; 224130561Sobrien 225130561Sobrien expr.X_op = O_symbol; 226130561Sobrien expr.X_add_symbol = symbol; 227130561Sobrien expr.X_add_number = 0; 228130561Sobrien emit_expr (&expr, size); 229130561Sobrien} 230130561Sobrien#endif 231130561Sobrien 23277298Sobrien/* Find or create an entry for SEG+SUBSEG in ALL_SEGS. */ 23377298Sobrien 23477298Sobrienstatic struct line_subseg * 235130561Sobrienget_line_subseg (segT seg, subsegT subseg) 23677298Sobrien{ 23777298Sobrien static segT last_seg; 23877298Sobrien static subsegT last_subseg; 23977298Sobrien static struct line_subseg *last_line_subseg; 24077298Sobrien 241218822Sdim struct line_seg **ps, *s; 24277298Sobrien struct line_subseg **pss, *ss; 24377298Sobrien 24477298Sobrien if (seg == last_seg && subseg == last_subseg) 24577298Sobrien return last_line_subseg; 24677298Sobrien 247218822Sdim for (ps = &all_segs; (s = *ps) != NULL; ps = &s->next) 24877298Sobrien if (s->seg == seg) 24977298Sobrien goto found_seg; 25077298Sobrien 25177298Sobrien s = (struct line_seg *) xmalloc (sizeof (*s)); 252218822Sdim s->next = NULL; 25377298Sobrien s->seg = seg; 25477298Sobrien s->head = NULL; 255218822Sdim *ps = s; 25677298Sobrien 25777298Sobrien found_seg: 25877298Sobrien for (pss = &s->head; (ss = *pss) != NULL ; pss = &ss->next) 25960484Sobrien { 26077298Sobrien if (ss->subseg == subseg) 26177298Sobrien goto found_subseg; 26277298Sobrien if (ss->subseg > subseg) 26377298Sobrien break; 26460484Sobrien } 26560484Sobrien 26677298Sobrien ss = (struct line_subseg *) xmalloc (sizeof (*ss)); 26777298Sobrien ss->next = *pss; 26877298Sobrien ss->subseg = subseg; 26977298Sobrien ss->head = NULL; 27077298Sobrien ss->ptail = &ss->head; 27177298Sobrien *pss = ss; 27260484Sobrien 27377298Sobrien found_subseg: 27477298Sobrien last_seg = seg; 27577298Sobrien last_subseg = subseg; 27677298Sobrien last_line_subseg = ss; 27760484Sobrien 27877298Sobrien return ss; 27977298Sobrien} 28060484Sobrien 281218822Sdim/* Record an entry for LOC occurring at LABEL. */ 282218822Sdim 283218822Sdimstatic void 284218822Sdimdwarf2_gen_line_info_1 (symbolS *label, struct dwarf2_line_info *loc) 285218822Sdim{ 286218822Sdim struct line_subseg *ss; 287218822Sdim struct line_entry *e; 288218822Sdim 289218822Sdim e = (struct line_entry *) xmalloc (sizeof (*e)); 290218822Sdim e->next = NULL; 291218822Sdim e->label = label; 292218822Sdim e->loc = *loc; 293218822Sdim 294218822Sdim ss = get_line_subseg (now_seg, now_subseg); 295218822Sdim *ss->ptail = e; 296218822Sdim ss->ptail = &e->next; 297218822Sdim} 298218822Sdim 299130561Sobrien/* Record an entry for LOC occurring at OFS within the current fragment. */ 30060484Sobrien 30177298Sobrienvoid 302130561Sobriendwarf2_gen_line_info (addressT ofs, struct dwarf2_line_info *loc) 30360484Sobrien{ 30489857Sobrien static unsigned int line = -1; 30589857Sobrien static unsigned int filenum = -1; 30660484Sobrien 307218822Sdim symbolS *sym; 308218822Sdim 30977298Sobrien /* Early out for as-yet incomplete location information. */ 31077298Sobrien if (loc->filenum == 0 || loc->line == 0) 31177298Sobrien return; 31277298Sobrien 313104834Sobrien /* Don't emit sequences of line symbols for the same line when the 314104834Sobrien symbols apply to assembler code. It is necessary to emit 315104834Sobrien duplicate line symbols when a compiler asks for them, because GDB 316104834Sobrien uses them to determine the end of the prologue. */ 317104834Sobrien if (debug_type == DEBUG_DWARF2 318104834Sobrien && line == loc->line && filenum == loc->filenum) 31989857Sobrien return; 32089857Sobrien 32189857Sobrien line = loc->line; 32289857Sobrien filenum = loc->filenum; 32389857Sobrien 324218822Sdim sym = symbol_temp_new (now_seg, ofs, frag_now); 325218822Sdim dwarf2_gen_line_info_1 (sym, loc); 32677298Sobrien} 32777298Sobrien 328218822Sdim/* Returns the current source information. If .file directives have 329218822Sdim been encountered, the info for the corresponding source file is 330218822Sdim returned. Otherwise, the info for the assembly source file is 331218822Sdim returned. */ 332218822Sdim 33377298Sobrienvoid 334130561Sobriendwarf2_where (struct dwarf2_line_info *line) 33577298Sobrien{ 33677298Sobrien if (debug_type == DEBUG_DWARF2) 33760484Sobrien { 33877298Sobrien char *filename; 33977298Sobrien as_where (&filename, &line->line); 340130561Sobrien line->filenum = get_filenum (filename, 0); 34177298Sobrien line->column = 0; 342218822Sdim line->flags = DWARF2_FLAG_IS_STMT; 343218822Sdim line->isa = current.isa; 34460484Sobrien } 34577298Sobrien else 34677298Sobrien *line = current; 34760484Sobrien} 34860484Sobrien 349218822Sdim/* A hook to allow the target backend to inform the line number state 350218822Sdim machine of isa changes when assembler debug info is enabled. */ 351218822Sdim 352218822Sdimvoid 353218822Sdimdwarf2_set_isa (unsigned int isa) 354218822Sdim{ 355218822Sdim current.isa = isa; 356218822Sdim} 357218822Sdim 35877298Sobrien/* Called for each machine instruction, or relatively atomic group of 35977298Sobrien machine instructions (ie built-in macro). The instruction or group 36077298Sobrien is SIZE bytes in length. If dwarf2 line number generation is called 36177298Sobrien for, emit a line statement appropriately. */ 36277298Sobrien 36377298Sobrienvoid 364130561Sobriendwarf2_emit_insn (int size) 36560484Sobrien{ 36677298Sobrien struct dwarf2_line_info loc; 36760484Sobrien 368104834Sobrien if (loc_directive_seen) 369104834Sobrien { 370104834Sobrien /* Use the last location established by a .loc directive, not 371104834Sobrien the value returned by dwarf2_where(). That calls as_where() 372104834Sobrien which will return either the logical input file name (foo.c) 373104834Sobrien or the physical input file name (foo.s) and not the file name 374104834Sobrien specified in the most recent .loc directive (eg foo.h). */ 375104834Sobrien loc = current; 376104834Sobrien 377104834Sobrien /* Unless we generate DWARF2 debugging information for each 378104834Sobrien assembler line, we only emit one line symbol for one LOC. */ 379104834Sobrien if (debug_type != DEBUG_DWARF2) 380130561Sobrien loc_directive_seen = FALSE; 381104834Sobrien } 382104834Sobrien else if (debug_type != DEBUG_DWARF2) 38377298Sobrien return; 384104834Sobrien else 385218822Sdim dwarf2_where (&loc); 38677298Sobrien 38777298Sobrien dwarf2_gen_line_info (frag_now_fix () - size, &loc); 388218822Sdim 389218822Sdim current.flags &= ~(DWARF2_FLAG_BASIC_BLOCK 390218822Sdim | DWARF2_FLAG_PROLOGUE_END 391218822Sdim | DWARF2_FLAG_EPILOGUE_BEGIN); 39277298Sobrien} 39377298Sobrien 394218822Sdim/* Called for each (preferably code) label. If dwarf2_loc_mark_labels 395218822Sdim is enabled, emit a basic block marker. */ 396218822Sdim 397218822Sdimvoid 398218822Sdimdwarf2_emit_label (symbolS *label) 399218822Sdim{ 400218822Sdim struct dwarf2_line_info loc; 401218822Sdim 402218822Sdim if (!dwarf2_loc_mark_labels) 403218822Sdim return; 404218822Sdim if (S_GET_SEGMENT (label) != now_seg) 405218822Sdim return; 406218822Sdim if (!(bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE)) 407218822Sdim return; 408218822Sdim 409218822Sdim if (debug_type == DEBUG_DWARF2) 410218822Sdim dwarf2_where (&loc); 411218822Sdim else 412218822Sdim { 413218822Sdim loc = current; 414218822Sdim loc_directive_seen = FALSE; 415218822Sdim } 416218822Sdim 417218822Sdim loc.flags |= DWARF2_FLAG_BASIC_BLOCK; 418218822Sdim 419218822Sdim current.flags &= ~(DWARF2_FLAG_BASIC_BLOCK 420218822Sdim | DWARF2_FLAG_PROLOGUE_END 421218822Sdim | DWARF2_FLAG_EPILOGUE_BEGIN); 422218822Sdim 423218822Sdim dwarf2_gen_line_info_1 (label, &loc); 424218822Sdim} 425218822Sdim 426130561Sobrien/* Get a .debug_line file number for FILENAME. If NUM is nonzero, 427130561Sobrien allocate it on that file table slot, otherwise return the first 428130561Sobrien empty one. */ 42977298Sobrien 43077298Sobrienstatic unsigned int 431130561Sobrienget_filenum (const char *filename, unsigned int num) 43277298Sobrien{ 433130561Sobrien static unsigned int last_used, last_used_dir_len; 434130561Sobrien const char *file; 435130561Sobrien size_t dir_len; 436130561Sobrien unsigned int i, dir; 43777298Sobrien 438130561Sobrien if (num == 0 && last_used) 439130561Sobrien { 440130561Sobrien if (! files[last_used].dir 441130561Sobrien && strcmp (filename, files[last_used].filename) == 0) 442130561Sobrien return last_used; 443130561Sobrien if (files[last_used].dir 444130561Sobrien && strncmp (filename, dirs[files[last_used].dir], 445130561Sobrien last_used_dir_len) == 0 446130561Sobrien && IS_DIR_SEPARATOR (filename [last_used_dir_len]) 447130561Sobrien && strcmp (filename + last_used_dir_len + 1, 448130561Sobrien files[last_used].filename) == 0) 449130561Sobrien return last_used; 450130561Sobrien } 45177298Sobrien 452130561Sobrien file = lbasename (filename); 453130561Sobrien /* Don't make empty string from / or A: from A:/ . */ 454130561Sobrien#ifdef HAVE_DOS_BASED_FILE_SYSTEM 455130561Sobrien if (file <= filename + 3) 456130561Sobrien file = filename; 457130561Sobrien#else 458130561Sobrien if (file == filename + 1) 459130561Sobrien file = filename; 460130561Sobrien#endif 461130561Sobrien dir_len = file - filename; 46277298Sobrien 463130561Sobrien dir = 0; 464130561Sobrien if (dir_len) 465130561Sobrien { 466130561Sobrien --dir_len; 467130561Sobrien for (dir = 1; dir < dirs_in_use; ++dir) 468130561Sobrien if (strncmp (filename, dirs[dir], dir_len) == 0 469130561Sobrien && dirs[dir][dir_len] == '\0') 470130561Sobrien break; 471130561Sobrien 472130561Sobrien if (dir >= dirs_in_use) 473130561Sobrien { 474130561Sobrien if (dir >= dirs_allocated) 475130561Sobrien { 476130561Sobrien dirs_allocated = dir + 32; 477130561Sobrien dirs = (char **) 478130561Sobrien xrealloc (dirs, (dir + 32) * sizeof (const char *)); 479130561Sobrien } 480130561Sobrien 481130561Sobrien dirs[dir] = xmalloc (dir_len + 1); 482130561Sobrien memcpy (dirs[dir], filename, dir_len); 483130561Sobrien dirs[dir][dir_len] = '\0'; 484130561Sobrien dirs_in_use = dir + 1; 485130561Sobrien } 486130561Sobrien } 487130561Sobrien 488130561Sobrien if (num == 0) 489130561Sobrien { 490130561Sobrien for (i = 1; i < files_in_use; ++i) 491130561Sobrien if (files[i].dir == dir 492130561Sobrien && files[i].filename 493130561Sobrien && strcmp (file, files[i].filename) == 0) 494130561Sobrien { 495130561Sobrien last_used = i; 496130561Sobrien last_used_dir_len = dir_len; 497130561Sobrien return i; 498130561Sobrien } 499130561Sobrien } 500130561Sobrien else 501130561Sobrien i = num; 502130561Sobrien 50377298Sobrien if (i >= files_allocated) 50460484Sobrien { 50577298Sobrien unsigned int old = files_allocated; 50677298Sobrien 50777298Sobrien files_allocated = i + 32; 50877298Sobrien files = (struct file_entry *) 50977298Sobrien xrealloc (files, (i + 32) * sizeof (struct file_entry)); 51077298Sobrien 51177298Sobrien memset (files + old, 0, (i + 32 - old) * sizeof (struct file_entry)); 51260484Sobrien } 51377298Sobrien 514130561Sobrien files[i].filename = num ? file : xstrdup (file); 515130561Sobrien files[i].dir = dir; 516218822Sdim if (files_in_use < i + 1) 517218822Sdim files_in_use = i + 1; 51877298Sobrien last_used = i; 519130561Sobrien last_used_dir_len = dir_len; 52077298Sobrien 52177298Sobrien return i; 52260484Sobrien} 52360484Sobrien 524104834Sobrien/* Handle two forms of .file directive: 525104834Sobrien - Pass .file "source.c" to s_app_file 526104834Sobrien - Handle .file 1 "source.c" by adding an entry to the DWARF-2 file table 52777298Sobrien 528104834Sobrien If an entry is added to the file table, return a pointer to the filename. */ 529104834Sobrien 530104834Sobrienchar * 531130561Sobriendwarf2_directive_file (int dummy ATTRIBUTE_UNUSED) 53260484Sobrien{ 53377298Sobrien offsetT num; 53478828Sobrien char *filename; 53577298Sobrien int filename_len; 53660484Sobrien 53777298Sobrien /* Continue to accept a bare string and pass it off. */ 53877298Sobrien SKIP_WHITESPACE (); 53977298Sobrien if (*input_line_pointer == '"') 54060484Sobrien { 54177298Sobrien s_app_file (0); 542104834Sobrien return NULL; 54360484Sobrien } 54460484Sobrien 54577298Sobrien num = get_absolute_expression (); 54677298Sobrien filename = demand_copy_C_string (&filename_len); 547218822Sdim if (filename == NULL) 548218822Sdim return NULL; 54977298Sobrien demand_empty_rest_of_line (); 55060484Sobrien 55177298Sobrien if (num < 1) 55260484Sobrien { 55389857Sobrien as_bad (_("file number less than one")); 554104834Sobrien return NULL; 55560484Sobrien } 55660484Sobrien 55789857Sobrien if (num < (int) files_in_use && files[num].filename != 0) 55860484Sobrien { 55989857Sobrien as_bad (_("file number %ld already allocated"), (long) num); 560104834Sobrien return NULL; 56160484Sobrien } 56260484Sobrien 563130561Sobrien get_filenum (filename, num); 56460484Sobrien 565104834Sobrien return filename; 56660484Sobrien} 56760484Sobrien 56877298Sobrienvoid 569130561Sobriendwarf2_directive_loc (int dummy ATTRIBUTE_UNUSED) 57077298Sobrien{ 571218822Sdim offsetT filenum, line; 57277298Sobrien 57377298Sobrien filenum = get_absolute_expression (); 57477298Sobrien SKIP_WHITESPACE (); 57577298Sobrien line = get_absolute_expression (); 57677298Sobrien 57777298Sobrien if (filenum < 1) 57877298Sobrien { 57989857Sobrien as_bad (_("file number less than one")); 58077298Sobrien return; 58177298Sobrien } 58277298Sobrien if (filenum >= (int) files_in_use || files[filenum].filename == 0) 58377298Sobrien { 58489857Sobrien as_bad (_("unassigned file number %ld"), (long) filenum); 58577298Sobrien return; 58677298Sobrien } 58777298Sobrien 58877298Sobrien current.filenum = filenum; 58977298Sobrien current.line = line; 59077298Sobrien 59177298Sobrien#ifndef NO_LISTING 59277298Sobrien if (listing) 593104834Sobrien { 594130561Sobrien if (files[filenum].dir) 595130561Sobrien { 596130561Sobrien size_t dir_len = strlen (dirs[files[filenum].dir]); 597130561Sobrien size_t file_len = strlen (files[filenum].filename); 598130561Sobrien char *cp = (char *) alloca (dir_len + 1 + file_len + 1); 599130561Sobrien 600130561Sobrien memcpy (cp, dirs[files[filenum].dir], dir_len); 601218822Sdim INSERT_DIR_SEPARATOR (cp, dir_len); 602130561Sobrien memcpy (cp + dir_len + 1, files[filenum].filename, file_len); 603130561Sobrien cp[dir_len + file_len + 1] = '\0'; 604130561Sobrien listing_source_file (cp); 605130561Sobrien } 606130561Sobrien else 607130561Sobrien listing_source_file (files[filenum].filename); 608104834Sobrien listing_source_line (line); 609104834Sobrien } 61077298Sobrien#endif 611218822Sdim 612218822Sdim SKIP_WHITESPACE (); 613218822Sdim if (ISDIGIT (*input_line_pointer)) 614218822Sdim { 615218822Sdim current.column = get_absolute_expression (); 616218822Sdim SKIP_WHITESPACE (); 617218822Sdim } 618218822Sdim 619218822Sdim while (ISALPHA (*input_line_pointer)) 620218822Sdim { 621218822Sdim char *p, c; 622218822Sdim offsetT value; 623218822Sdim 624218822Sdim p = input_line_pointer; 625218822Sdim c = get_symbol_end (); 626218822Sdim 627218822Sdim if (strcmp (p, "basic_block") == 0) 628218822Sdim { 629218822Sdim current.flags |= DWARF2_FLAG_BASIC_BLOCK; 630218822Sdim *input_line_pointer = c; 631218822Sdim } 632218822Sdim else if (strcmp (p, "prologue_end") == 0) 633218822Sdim { 634218822Sdim current.flags |= DWARF2_FLAG_PROLOGUE_END; 635218822Sdim *input_line_pointer = c; 636218822Sdim } 637218822Sdim else if (strcmp (p, "epilogue_begin") == 0) 638218822Sdim { 639218822Sdim current.flags |= DWARF2_FLAG_EPILOGUE_BEGIN; 640218822Sdim *input_line_pointer = c; 641218822Sdim } 642218822Sdim else if (strcmp (p, "is_stmt") == 0) 643218822Sdim { 644218822Sdim *input_line_pointer = c; 645218822Sdim value = get_absolute_expression (); 646218822Sdim if (value == 0) 647218822Sdim current.flags &= ~DWARF2_FLAG_IS_STMT; 648218822Sdim else if (value == 1) 649218822Sdim current.flags |= DWARF2_FLAG_IS_STMT; 650218822Sdim else 651218822Sdim { 652218822Sdim as_bad (_("is_stmt value not 0 or 1")); 653218822Sdim return; 654218822Sdim } 655218822Sdim } 656218822Sdim else if (strcmp (p, "isa") == 0) 657218822Sdim { 658218822Sdim *input_line_pointer = c; 659218822Sdim value = get_absolute_expression (); 660218822Sdim if (value >= 0) 661218822Sdim current.isa = value; 662218822Sdim else 663218822Sdim { 664218822Sdim as_bad (_("isa number less than zero")); 665218822Sdim return; 666218822Sdim } 667218822Sdim } 668218822Sdim else 669218822Sdim { 670218822Sdim as_bad (_("unknown .loc sub-directive `%s'"), p); 671218822Sdim *input_line_pointer = c; 672218822Sdim return; 673218822Sdim } 674218822Sdim 675218822Sdim SKIP_WHITESPACE (); 676218822Sdim } 677218822Sdim 678218822Sdim demand_empty_rest_of_line (); 679218822Sdim loc_directive_seen = TRUE; 68077298Sobrien} 681218822Sdim 682218822Sdimvoid 683218822Sdimdwarf2_directive_loc_mark_labels (int dummy ATTRIBUTE_UNUSED) 684218822Sdim{ 685218822Sdim offsetT value = get_absolute_expression (); 686218822Sdim 687218822Sdim if (value != 0 && value != 1) 688218822Sdim { 689218822Sdim as_bad (_("expected 0 or 1")); 690218822Sdim ignore_rest_of_line (); 691218822Sdim } 692218822Sdim else 693218822Sdim { 694218822Sdim dwarf2_loc_mark_labels = value != 0; 695218822Sdim demand_empty_rest_of_line (); 696218822Sdim } 697218822Sdim} 69877298Sobrien 69977298Sobrienstatic struct frag * 700130561Sobrienfirst_frag_for_seg (segT seg) 70177298Sobrien{ 702218822Sdim return seg_info (seg)->frchainP->frch_root; 70377298Sobrien} 70477298Sobrien 70577298Sobrienstatic struct frag * 706130561Sobrienlast_frag_for_seg (segT seg) 70777298Sobrien{ 708218822Sdim frchainS *f = seg_info (seg)->frchainP; 70977298Sobrien 710218822Sdim while (f->frch_next != NULL) 711218822Sdim f = f->frch_next; 71277298Sobrien 713218822Sdim return f->frch_last; 71477298Sobrien} 71577298Sobrien 71677298Sobrien/* Emit a single byte into the current segment. */ 71777298Sobrien 71877298Sobrienstatic inline void 719130561Sobrienout_byte (int byte) 72077298Sobrien{ 72177298Sobrien FRAG_APPEND_1_CHAR (byte); 72277298Sobrien} 72377298Sobrien 72477298Sobrien/* Emit a statement program opcode into the current segment. */ 72577298Sobrien 72677298Sobrienstatic inline void 727130561Sobrienout_opcode (int opc) 72877298Sobrien{ 72977298Sobrien out_byte (opc); 73077298Sobrien} 73177298Sobrien 73277298Sobrien/* Emit a two-byte word into the current segment. */ 73377298Sobrien 73477298Sobrienstatic inline void 735130561Sobrienout_two (int data) 73677298Sobrien{ 73777298Sobrien md_number_to_chars (frag_more (2), data, 2); 73877298Sobrien} 73977298Sobrien 74077298Sobrien/* Emit a four byte word into the current segment. */ 74177298Sobrien 74277298Sobrienstatic inline void 743130561Sobrienout_four (int data) 74477298Sobrien{ 74577298Sobrien md_number_to_chars (frag_more (4), data, 4); 74677298Sobrien} 74777298Sobrien 74877298Sobrien/* Emit an unsigned "little-endian base 128" number. */ 74977298Sobrien 75060484Sobrienstatic void 751130561Sobrienout_uleb128 (addressT value) 75260484Sobrien{ 75377298Sobrien output_leb128 (frag_more (sizeof_leb128 (value, 0)), value, 0); 75477298Sobrien} 75560484Sobrien 756218822Sdim/* Emit a signed "little-endian base 128" number. */ 757218822Sdim 758218822Sdimstatic void 759218822Sdimout_sleb128 (addressT value) 760218822Sdim{ 761218822Sdim output_leb128 (frag_more (sizeof_leb128 (value, 1)), value, 1); 762218822Sdim} 763218822Sdim 76477298Sobrien/* Emit a tuple for .debug_abbrev. */ 76577298Sobrien 76677298Sobrienstatic inline void 767130561Sobrienout_abbrev (int name, int form) 76877298Sobrien{ 76977298Sobrien out_uleb128 (name); 77077298Sobrien out_uleb128 (form); 77160484Sobrien} 77260484Sobrien 77377298Sobrien/* Get the size of a fragment. */ 77460484Sobrien 77577298Sobrienstatic offsetT 776218822Sdimget_frag_fix (fragS *frag, segT seg) 77777298Sobrien{ 77877298Sobrien frchainS *fr; 77960484Sobrien 78077298Sobrien if (frag->fr_next) 78177298Sobrien return frag->fr_fix; 78260484Sobrien 78377298Sobrien /* If a fragment is the last in the chain, special measures must be 78477298Sobrien taken to find its size before relaxation, since it may be pending 78577298Sobrien on some subsegment chain. */ 786218822Sdim for (fr = seg_info (seg)->frchainP; fr; fr = fr->frch_next) 78777298Sobrien if (fr->frch_last == frag) 788130561Sobrien return (char *) obstack_next_free (&fr->frch_obstack) - frag->fr_literal; 78960484Sobrien 79077298Sobrien abort (); 79177298Sobrien} 79277298Sobrien 79377298Sobrien/* Set an absolute address (may result in a relocation entry). */ 79477298Sobrien 79577298Sobrienstatic void 796218822Sdimout_set_addr (symbolS *sym) 79777298Sobrien{ 79877298Sobrien expressionS expr; 79977298Sobrien 80060484Sobrien out_opcode (DW_LNS_extended_op); 80177298Sobrien out_uleb128 (sizeof_address + 1); 80260484Sobrien 80360484Sobrien out_opcode (DW_LNE_set_address); 80460484Sobrien expr.X_op = O_symbol; 80560484Sobrien expr.X_add_symbol = sym; 80660484Sobrien expr.X_add_number = 0; 80777298Sobrien emit_expr (&expr, sizeof_address); 80860484Sobrien} 80960484Sobrien 810130561Sobrien#if DWARF2_LINE_MIN_INSN_LENGTH > 1 811130561Sobrienstatic void scale_addr_delta (addressT *); 812130561Sobrien 813130561Sobrienstatic void 814130561Sobrienscale_addr_delta (addressT *addr_delta) 815130561Sobrien{ 816130561Sobrien static int printed_this = 0; 817130561Sobrien if (*addr_delta % DWARF2_LINE_MIN_INSN_LENGTH != 0) 818130561Sobrien { 819130561Sobrien if (!printed_this) 820130561Sobrien as_bad("unaligned opcodes detected in executable segment"); 821130561Sobrien printed_this = 1; 822130561Sobrien } 823130561Sobrien *addr_delta /= DWARF2_LINE_MIN_INSN_LENGTH; 824130561Sobrien} 825130561Sobrien#else 826130561Sobrien#define scale_addr_delta(A) 827130561Sobrien#endif 828130561Sobrien 82977298Sobrien/* Encode a pair of line and address skips as efficiently as possible. 83077298Sobrien Note that the line skip is signed, whereas the address skip is unsigned. 83177298Sobrien 83277298Sobrien The following two routines *must* be kept in sync. This is 83377298Sobrien enforced by making emit_inc_line_addr abort if we do not emit 83477298Sobrien exactly the expected number of bytes. */ 83577298Sobrien 83677298Sobrienstatic int 837130561Sobriensize_inc_line_addr (int line_delta, addressT addr_delta) 83860484Sobrien{ 83977298Sobrien unsigned int tmp, opcode; 84077298Sobrien int len = 0; 84160484Sobrien 84277298Sobrien /* Scale the address delta by the minimum instruction length. */ 843130561Sobrien scale_addr_delta (&addr_delta); 84477298Sobrien 84577298Sobrien /* INT_MAX is a signal that this is actually a DW_LNE_end_sequence. 84677298Sobrien We cannot use special opcodes here, since we want the end_sequence 84777298Sobrien to emit the matrix entry. */ 84877298Sobrien if (line_delta == INT_MAX) 84960484Sobrien { 85077298Sobrien if (addr_delta == MAX_SPECIAL_ADDR_DELTA) 85177298Sobrien len = 1; 85260484Sobrien else 85377298Sobrien len = 1 + sizeof_leb128 (addr_delta, 0); 85477298Sobrien return len + 3; 85560484Sobrien } 85660484Sobrien 85777298Sobrien /* Bias the line delta by the base. */ 85877298Sobrien tmp = line_delta - DWARF2_LINE_BASE; 85960484Sobrien 86077298Sobrien /* If the line increment is out of range of a special opcode, we 86177298Sobrien must encode it with DW_LNS_advance_line. */ 86277298Sobrien if (tmp >= DWARF2_LINE_RANGE) 86377298Sobrien { 86477298Sobrien len = 1 + sizeof_leb128 (line_delta, 1); 86577298Sobrien line_delta = 0; 86677298Sobrien tmp = 0 - DWARF2_LINE_BASE; 86777298Sobrien } 86877298Sobrien 86977298Sobrien /* Bias the opcode by the special opcode base. */ 87077298Sobrien tmp += DWARF2_LINE_OPCODE_BASE; 87177298Sobrien 87277298Sobrien /* Avoid overflow when addr_delta is large. */ 87377298Sobrien if (addr_delta < 256 + MAX_SPECIAL_ADDR_DELTA) 87477298Sobrien { 87577298Sobrien /* Try using a special opcode. */ 87677298Sobrien opcode = tmp + addr_delta * DWARF2_LINE_RANGE; 87777298Sobrien if (opcode <= 255) 87877298Sobrien return len + 1; 87977298Sobrien 88077298Sobrien /* Try using DW_LNS_const_add_pc followed by special op. */ 88177298Sobrien opcode = tmp + (addr_delta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE; 88277298Sobrien if (opcode <= 255) 88377298Sobrien return len + 2; 88477298Sobrien } 88577298Sobrien 88677298Sobrien /* Otherwise use DW_LNS_advance_pc. */ 88777298Sobrien len += 1 + sizeof_leb128 (addr_delta, 0); 88877298Sobrien 88977298Sobrien /* DW_LNS_copy or special opcode. */ 89077298Sobrien len += 1; 89177298Sobrien 89277298Sobrien return len; 89360484Sobrien} 89460484Sobrien 89577298Sobrienstatic void 896130561Sobrienemit_inc_line_addr (int line_delta, addressT addr_delta, char *p, int len) 89760484Sobrien{ 89877298Sobrien unsigned int tmp, opcode; 89977298Sobrien int need_copy = 0; 90077298Sobrien char *end = p + len; 90160484Sobrien 902218822Sdim /* Line number sequences cannot go backward in addresses. This means 903218822Sdim we've incorrectly ordered the statements in the sequence. */ 904218822Sdim assert ((offsetT) addr_delta >= 0); 905218822Sdim 90677298Sobrien /* Scale the address delta by the minimum instruction length. */ 907130561Sobrien scale_addr_delta (&addr_delta); 908130561Sobrien 90977298Sobrien /* INT_MAX is a signal that this is actually a DW_LNE_end_sequence. 91077298Sobrien We cannot use special opcodes here, since we want the end_sequence 91177298Sobrien to emit the matrix entry. */ 91277298Sobrien if (line_delta == INT_MAX) 91360484Sobrien { 91477298Sobrien if (addr_delta == MAX_SPECIAL_ADDR_DELTA) 91577298Sobrien *p++ = DW_LNS_const_add_pc; 91677298Sobrien else 91760484Sobrien { 91877298Sobrien *p++ = DW_LNS_advance_pc; 91977298Sobrien p += output_leb128 (p, addr_delta, 0); 92060484Sobrien } 92177298Sobrien 92277298Sobrien *p++ = DW_LNS_extended_op; 92377298Sobrien *p++ = 1; 92477298Sobrien *p++ = DW_LNE_end_sequence; 92577298Sobrien goto done; 92660484Sobrien } 92760484Sobrien 92877298Sobrien /* Bias the line delta by the base. */ 92977298Sobrien tmp = line_delta - DWARF2_LINE_BASE; 93077298Sobrien 93177298Sobrien /* If the line increment is out of range of a special opcode, we 93277298Sobrien must encode it with DW_LNS_advance_line. */ 93377298Sobrien if (tmp >= DWARF2_LINE_RANGE) 93460484Sobrien { 93577298Sobrien *p++ = DW_LNS_advance_line; 93677298Sobrien p += output_leb128 (p, line_delta, 1); 93760484Sobrien 93877298Sobrien line_delta = 0; 93977298Sobrien tmp = 0 - DWARF2_LINE_BASE; 94077298Sobrien need_copy = 1; 94177298Sobrien } 94260484Sobrien 943218822Sdim /* Prettier, I think, to use DW_LNS_copy instead of a "line +0, addr +0" 944218822Sdim special opcode. */ 945218822Sdim if (line_delta == 0 && addr_delta == 0) 946218822Sdim { 947218822Sdim *p++ = DW_LNS_copy; 948218822Sdim goto done; 949218822Sdim } 950218822Sdim 95177298Sobrien /* Bias the opcode by the special opcode base. */ 95277298Sobrien tmp += DWARF2_LINE_OPCODE_BASE; 95360484Sobrien 95477298Sobrien /* Avoid overflow when addr_delta is large. */ 95577298Sobrien if (addr_delta < 256 + MAX_SPECIAL_ADDR_DELTA) 95660484Sobrien { 95777298Sobrien /* Try using a special opcode. */ 95877298Sobrien opcode = tmp + addr_delta * DWARF2_LINE_RANGE; 95977298Sobrien if (opcode <= 255) 96060484Sobrien { 96177298Sobrien *p++ = opcode; 96277298Sobrien goto done; 96360484Sobrien } 96477298Sobrien 96577298Sobrien /* Try using DW_LNS_const_add_pc followed by special op. */ 96677298Sobrien opcode = tmp + (addr_delta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE; 96777298Sobrien if (opcode <= 255) 96877298Sobrien { 96977298Sobrien *p++ = DW_LNS_const_add_pc; 97077298Sobrien *p++ = opcode; 97177298Sobrien goto done; 97277298Sobrien } 97360484Sobrien } 97477298Sobrien 97577298Sobrien /* Otherwise use DW_LNS_advance_pc. */ 97677298Sobrien *p++ = DW_LNS_advance_pc; 97777298Sobrien p += output_leb128 (p, addr_delta, 0); 97877298Sobrien 97977298Sobrien if (need_copy) 98077298Sobrien *p++ = DW_LNS_copy; 98160484Sobrien else 98277298Sobrien *p++ = tmp; 98360484Sobrien 98477298Sobrien done: 98577298Sobrien assert (p == end); 98677298Sobrien} 98760484Sobrien 98877298Sobrien/* Handy routine to combine calls to the above two routines. */ 98960484Sobrien 99077298Sobrienstatic void 991130561Sobrienout_inc_line_addr (int line_delta, addressT addr_delta) 99277298Sobrien{ 99377298Sobrien int len = size_inc_line_addr (line_delta, addr_delta); 99477298Sobrien emit_inc_line_addr (line_delta, addr_delta, frag_more (len), len); 99577298Sobrien} 99660484Sobrien 997218822Sdim/* Write out an alternative form of line and address skips using 998218822Sdim DW_LNS_fixed_advance_pc opcodes. This uses more space than the default 999218822Sdim line and address information, but it helps support linker relaxation that 1000218822Sdim changes the code offsets. */ 1001218822Sdim 1002218822Sdimstatic void 1003218822Sdimout_fixed_inc_line_addr (int line_delta, symbolS *to_sym, symbolS *from_sym) 1004218822Sdim{ 1005218822Sdim expressionS expr; 1006218822Sdim 1007218822Sdim /* INT_MAX is a signal that this is actually a DW_LNE_end_sequence. */ 1008218822Sdim if (line_delta == INT_MAX) 1009218822Sdim { 1010218822Sdim out_opcode (DW_LNS_fixed_advance_pc); 1011218822Sdim expr.X_op = O_subtract; 1012218822Sdim expr.X_add_symbol = to_sym; 1013218822Sdim expr.X_op_symbol = from_sym; 1014218822Sdim expr.X_add_number = 0; 1015218822Sdim emit_expr (&expr, 2); 1016218822Sdim 1017218822Sdim out_opcode (DW_LNS_extended_op); 1018218822Sdim out_byte (1); 1019218822Sdim out_opcode (DW_LNE_end_sequence); 1020218822Sdim return; 1021218822Sdim } 1022218822Sdim 1023218822Sdim out_opcode (DW_LNS_advance_line); 1024218822Sdim out_sleb128 (line_delta); 1025218822Sdim 1026218822Sdim out_opcode (DW_LNS_fixed_advance_pc); 1027218822Sdim expr.X_op = O_subtract; 1028218822Sdim expr.X_add_symbol = to_sym; 1029218822Sdim expr.X_op_symbol = from_sym; 1030218822Sdim expr.X_add_number = 0; 1031218822Sdim emit_expr (&expr, 2); 1032218822Sdim 1033218822Sdim out_opcode (DW_LNS_copy); 1034218822Sdim} 1035218822Sdim 103677298Sobrien/* Generate a variant frag that we can use to relax address/line 103777298Sobrien increments between fragments of the target segment. */ 103860484Sobrien 103977298Sobrienstatic void 1040218822Sdimrelax_inc_line_addr (int line_delta, symbolS *to_sym, symbolS *from_sym) 104177298Sobrien{ 104277298Sobrien expressionS expr; 104377298Sobrien int max_chars; 104460484Sobrien 104577298Sobrien expr.X_op = O_subtract; 104677298Sobrien expr.X_add_symbol = to_sym; 104777298Sobrien expr.X_op_symbol = from_sym; 104877298Sobrien expr.X_add_number = 0; 104960484Sobrien 105077298Sobrien /* The maximum size of the frag is the line delta with a maximum 105177298Sobrien sized address delta. */ 105277298Sobrien max_chars = size_inc_line_addr (line_delta, -DWARF2_LINE_MIN_INSN_LENGTH); 105360484Sobrien 105477298Sobrien frag_var (rs_dwarf2dbg, max_chars, max_chars, 1, 105577298Sobrien make_expr_symbol (&expr), line_delta, NULL); 105677298Sobrien} 105760484Sobrien 105877298Sobrien/* The function estimates the size of a rs_dwarf2dbg variant frag 105977298Sobrien based on the current values of the symbols. It is called before 106077298Sobrien the relaxation loop. We set fr_subtype to the expected length. */ 106160484Sobrien 106277298Sobrienint 1063130561Sobriendwarf2dbg_estimate_size_before_relax (fragS *frag) 106477298Sobrien{ 106577298Sobrien offsetT addr_delta; 106677298Sobrien int size; 106760484Sobrien 106889857Sobrien addr_delta = resolve_symbol_value (frag->fr_symbol); 106977298Sobrien size = size_inc_line_addr (frag->fr_offset, addr_delta); 107060484Sobrien 107177298Sobrien frag->fr_subtype = size; 107260484Sobrien 107377298Sobrien return size; 107460484Sobrien} 107560484Sobrien 107677298Sobrien/* This function relaxes a rs_dwarf2dbg variant frag based on the 107777298Sobrien current values of the symbols. fr_subtype is the current length 107877298Sobrien of the frag. This returns the change in frag length. */ 107977298Sobrien 108077298Sobrienint 1081130561Sobriendwarf2dbg_relax_frag (fragS *frag) 108277298Sobrien{ 108377298Sobrien int old_size, new_size; 108477298Sobrien 108577298Sobrien old_size = frag->fr_subtype; 108677298Sobrien new_size = dwarf2dbg_estimate_size_before_relax (frag); 108777298Sobrien 108877298Sobrien return new_size - old_size; 108977298Sobrien} 109077298Sobrien 109177298Sobrien/* This function converts a rs_dwarf2dbg variant frag into a normal 109277298Sobrien fill frag. This is called after all relaxation has been done. 109377298Sobrien fr_subtype will be the desired length of the frag. */ 109477298Sobrien 109577298Sobrienvoid 1096130561Sobriendwarf2dbg_convert_frag (fragS *frag) 109777298Sobrien{ 109877298Sobrien offsetT addr_diff; 109977298Sobrien 110089857Sobrien addr_diff = resolve_symbol_value (frag->fr_symbol); 110177298Sobrien 110277298Sobrien /* fr_var carries the max_chars that we created the fragment with. 110377298Sobrien fr_subtype carries the current expected length. We must, of 110477298Sobrien course, have allocated enough memory earlier. */ 110577298Sobrien assert (frag->fr_var >= (int) frag->fr_subtype); 110677298Sobrien 110777298Sobrien emit_inc_line_addr (frag->fr_offset, addr_diff, 110877298Sobrien frag->fr_literal + frag->fr_fix, frag->fr_subtype); 110977298Sobrien 111077298Sobrien frag->fr_fix += frag->fr_subtype; 111177298Sobrien frag->fr_type = rs_fill; 111277298Sobrien frag->fr_var = 0; 111377298Sobrien frag->fr_offset = 0; 111477298Sobrien} 111577298Sobrien 111677298Sobrien/* Generate .debug_line content for the chain of line number entries 111777298Sobrien beginning at E, for segment SEG. */ 111877298Sobrien 111960484Sobrienstatic void 1120130561Sobrienprocess_entries (segT seg, struct line_entry *e) 112160484Sobrien{ 112277298Sobrien unsigned filenum = 1; 112377298Sobrien unsigned line = 1; 112477298Sobrien unsigned column = 0; 1125218822Sdim unsigned isa = 0; 1126218822Sdim unsigned flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1127218822Sdim fragS *last_frag = NULL, *frag; 1128218822Sdim addressT last_frag_ofs = 0, frag_ofs; 1129218822Sdim symbolS *last_lab = NULL, *lab; 113077298Sobrien struct line_entry *next; 113160484Sobrien 1132218822Sdim do 113377298Sobrien { 1134218822Sdim int line_delta; 113560484Sobrien 113677298Sobrien if (filenum != e->loc.filenum) 113760484Sobrien { 113877298Sobrien filenum = e->loc.filenum; 113977298Sobrien out_opcode (DW_LNS_set_file); 114077298Sobrien out_uleb128 (filenum); 114177298Sobrien } 114277298Sobrien 114377298Sobrien if (column != e->loc.column) 114477298Sobrien { 114577298Sobrien column = e->loc.column; 114677298Sobrien out_opcode (DW_LNS_set_column); 114777298Sobrien out_uleb128 (column); 114877298Sobrien } 114977298Sobrien 1150218822Sdim if (isa != e->loc.isa) 115177298Sobrien { 1152218822Sdim isa = e->loc.isa; 1153218822Sdim out_opcode (DW_LNS_set_isa); 1154218822Sdim out_uleb128 (isa); 115577298Sobrien } 115677298Sobrien 1157218822Sdim if ((e->loc.flags ^ flags) & DWARF2_FLAG_IS_STMT) 115877298Sobrien { 1159218822Sdim flags = e->loc.flags; 1160218822Sdim out_opcode (DW_LNS_negate_stmt); 116177298Sobrien } 116277298Sobrien 1163218822Sdim if (e->loc.flags & DWARF2_FLAG_BASIC_BLOCK) 1164218822Sdim out_opcode (DW_LNS_set_basic_block); 1165218822Sdim 1166218822Sdim if (e->loc.flags & DWARF2_FLAG_PROLOGUE_END) 1167218822Sdim out_opcode (DW_LNS_set_prologue_end); 1168218822Sdim 1169218822Sdim if (e->loc.flags & DWARF2_FLAG_EPILOGUE_BEGIN) 1170218822Sdim out_opcode (DW_LNS_set_epilogue_begin); 1171218822Sdim 117278828Sobrien /* Don't try to optimize away redundant entries; gdb wants two 117378828Sobrien entries for a function where the code starts on the same line as 117478828Sobrien the {, and there's no way to identify that case here. Trust gcc 117578828Sobrien to optimize appropriately. */ 1176218822Sdim line_delta = e->loc.line - line; 1177218822Sdim lab = e->label; 1178218822Sdim frag = symbol_get_frag (lab); 1179218822Sdim frag_ofs = S_GET_VALUE (lab); 118077298Sobrien 1181218822Sdim if (last_frag == NULL) 118277298Sobrien { 1183218822Sdim out_set_addr (lab); 1184218822Sdim out_inc_line_addr (line_delta, 0); 118577298Sobrien } 1186218822Sdim else if (DWARF2_USE_FIXED_ADVANCE_PC) 1187218822Sdim out_fixed_inc_line_addr (line_delta, lab, last_lab); 1188218822Sdim else if (frag == last_frag) 1189218822Sdim out_inc_line_addr (line_delta, frag_ofs - last_frag_ofs); 1190218822Sdim else 1191218822Sdim relax_inc_line_addr (line_delta, lab, last_lab); 119277298Sobrien 1193218822Sdim line = e->loc.line; 1194218822Sdim last_lab = lab; 1195218822Sdim last_frag = frag; 1196218822Sdim last_frag_ofs = frag_ofs; 1197218822Sdim 119877298Sobrien next = e->next; 119977298Sobrien free (e); 120077298Sobrien e = next; 120160484Sobrien } 1202218822Sdim while (e); 120377298Sobrien 120477298Sobrien /* Emit a DW_LNE_end_sequence for the end of the section. */ 1205218822Sdim frag = last_frag_for_seg (seg); 1206218822Sdim frag_ofs = get_frag_fix (frag, seg); 1207218822Sdim if (DWARF2_USE_FIXED_ADVANCE_PC) 1208218822Sdim { 1209218822Sdim lab = symbol_temp_new (seg, frag_ofs, frag); 1210218822Sdim out_fixed_inc_line_addr (INT_MAX, lab, last_lab); 1211218822Sdim } 1212218822Sdim else if (frag == last_frag) 1213218822Sdim out_inc_line_addr (INT_MAX, frag_ofs - last_frag_ofs); 121477298Sobrien else 1215218822Sdim { 1216218822Sdim lab = symbol_temp_new (seg, frag_ofs, frag); 1217218822Sdim relax_inc_line_addr (INT_MAX, lab, last_lab); 1218218822Sdim } 121960484Sobrien} 122060484Sobrien 122177298Sobrien/* Emit the directory and file tables for .debug_line. */ 122277298Sobrien 122360484Sobrienstatic void 1224130561Sobrienout_file_list (void) 122560484Sobrien{ 122660484Sobrien size_t size; 122760484Sobrien char *cp; 122877298Sobrien unsigned int i; 122960484Sobrien 1230130561Sobrien /* Emit directory list. */ 1231130561Sobrien for (i = 1; i < dirs_in_use; ++i) 1232130561Sobrien { 1233130561Sobrien size = strlen (dirs[i]) + 1; 1234130561Sobrien cp = frag_more (size); 1235130561Sobrien memcpy (cp, dirs[i], size); 1236130561Sobrien } 1237130561Sobrien /* Terminate it. */ 123877298Sobrien out_byte ('\0'); 123977298Sobrien 124077298Sobrien for (i = 1; i < files_in_use; ++i) 124160484Sobrien { 124277298Sobrien if (files[i].filename == NULL) 124377298Sobrien { 124489857Sobrien as_bad (_("unassigned file number %ld"), (long) i); 1245130561Sobrien /* Prevent a crash later, particularly for file 1. */ 1246130561Sobrien files[i].filename = ""; 124777298Sobrien continue; 124877298Sobrien } 124977298Sobrien 125077298Sobrien size = strlen (files[i].filename) + 1; 125160484Sobrien cp = frag_more (size); 125277298Sobrien memcpy (cp, files[i].filename, size); 125360484Sobrien 125477298Sobrien out_uleb128 (files[i].dir); /* directory number */ 125560484Sobrien out_uleb128 (0); /* last modification timestamp */ 125660484Sobrien out_uleb128 (0); /* filesize */ 125760484Sobrien } 125877298Sobrien 125977298Sobrien /* Terminate filename list. */ 126077298Sobrien out_byte (0); 126160484Sobrien} 126260484Sobrien 126377298Sobrien/* Emit the collected .debug_line data. */ 126477298Sobrien 126560484Sobrienstatic void 1266130561Sobrienout_debug_line (segT line_seg) 126760484Sobrien{ 126877298Sobrien expressionS expr; 126977298Sobrien symbolS *line_start; 127077298Sobrien symbolS *prologue_end; 127177298Sobrien symbolS *line_end; 127277298Sobrien struct line_seg *s; 1273130561Sobrien enum dwarf2_format d2f; 1274130561Sobrien int sizeof_offset; 127577298Sobrien 127677298Sobrien subseg_set (line_seg, 0); 127777298Sobrien 1278130561Sobrien line_start = symbol_temp_new_now (); 1279130561Sobrien prologue_end = symbol_temp_make (); 1280130561Sobrien line_end = symbol_temp_make (); 128177298Sobrien 128277298Sobrien /* Total length of the information for this compilation unit. */ 128377298Sobrien expr.X_op = O_subtract; 128477298Sobrien expr.X_add_symbol = line_end; 128577298Sobrien expr.X_op_symbol = line_start; 128677298Sobrien 1287130561Sobrien d2f = DWARF2_FORMAT (); 1288130561Sobrien if (d2f == dwarf2_format_32bit) 1289130561Sobrien { 1290130561Sobrien expr.X_add_number = -4; 1291130561Sobrien emit_expr (&expr, 4); 1292130561Sobrien sizeof_offset = 4; 1293130561Sobrien } 1294130561Sobrien else if (d2f == dwarf2_format_64bit) 1295130561Sobrien { 1296130561Sobrien expr.X_add_number = -12; 1297130561Sobrien out_four (-1); 1298130561Sobrien emit_expr (&expr, 8); 1299130561Sobrien sizeof_offset = 8; 1300130561Sobrien } 1301130561Sobrien else if (d2f == dwarf2_format_64bit_irix) 1302130561Sobrien { 1303130561Sobrien expr.X_add_number = -8; 1304130561Sobrien emit_expr (&expr, 8); 1305130561Sobrien sizeof_offset = 8; 1306130561Sobrien } 1307130561Sobrien else 1308130561Sobrien { 1309130561Sobrien as_fatal (_("internal error: unknown dwarf2 format")); 1310130561Sobrien } 1311130561Sobrien 131277298Sobrien /* Version. */ 131377298Sobrien out_two (2); 131477298Sobrien 131577298Sobrien /* Length of the prologue following this length. */ 131677298Sobrien expr.X_op = O_subtract; 131777298Sobrien expr.X_add_symbol = prologue_end; 131877298Sobrien expr.X_op_symbol = line_start; 131977298Sobrien expr.X_add_number = - (4 + 2 + 4); 1320130561Sobrien emit_expr (&expr, sizeof_offset); 132177298Sobrien 132277298Sobrien /* Parameters of the state machine. */ 132377298Sobrien out_byte (DWARF2_LINE_MIN_INSN_LENGTH); 132477298Sobrien out_byte (DWARF2_LINE_DEFAULT_IS_STMT); 132577298Sobrien out_byte (DWARF2_LINE_BASE); 132677298Sobrien out_byte (DWARF2_LINE_RANGE); 132777298Sobrien out_byte (DWARF2_LINE_OPCODE_BASE); 132877298Sobrien 132977298Sobrien /* Standard opcode lengths. */ 133077298Sobrien out_byte (0); /* DW_LNS_copy */ 133177298Sobrien out_byte (1); /* DW_LNS_advance_pc */ 133277298Sobrien out_byte (1); /* DW_LNS_advance_line */ 133377298Sobrien out_byte (1); /* DW_LNS_set_file */ 133477298Sobrien out_byte (1); /* DW_LNS_set_column */ 133577298Sobrien out_byte (0); /* DW_LNS_negate_stmt */ 133677298Sobrien out_byte (0); /* DW_LNS_set_basic_block */ 133777298Sobrien out_byte (0); /* DW_LNS_const_add_pc */ 133877298Sobrien out_byte (1); /* DW_LNS_fixed_advance_pc */ 1339218822Sdim out_byte (0); /* DW_LNS_set_prologue_end */ 1340218822Sdim out_byte (0); /* DW_LNS_set_epilogue_begin */ 1341218822Sdim out_byte (1); /* DW_LNS_set_isa */ 134277298Sobrien 134377298Sobrien out_file_list (); 134477298Sobrien 1345130561Sobrien symbol_set_value_now (prologue_end); 134677298Sobrien 134777298Sobrien /* For each section, emit a statement program. */ 134877298Sobrien for (s = all_segs; s; s = s->next) 134977298Sobrien process_entries (s->seg, s->head->head); 135077298Sobrien 1351130561Sobrien symbol_set_value_now (line_end); 135277298Sobrien} 135377298Sobrien 1354218822Sdimstatic void 1355218822Sdimout_debug_ranges (segT ranges_seg) 1356218822Sdim{ 1357218822Sdim unsigned int addr_size = sizeof_address; 1358218822Sdim struct line_seg *s; 1359218822Sdim expressionS expr; 1360218822Sdim unsigned int i; 1361218822Sdim 1362218822Sdim subseg_set (ranges_seg, 0); 1363218822Sdim 1364218822Sdim /* Base Address Entry. */ 1365218822Sdim for (i = 0; i < addr_size; i++) 1366218822Sdim out_byte (0xff); 1367218822Sdim for (i = 0; i < addr_size; i++) 1368218822Sdim out_byte (0); 1369218822Sdim 1370218822Sdim /* Range List Entry. */ 1371218822Sdim for (s = all_segs; s; s = s->next) 1372218822Sdim { 1373218822Sdim fragS *frag; 1374218822Sdim symbolS *beg, *end; 1375218822Sdim 1376218822Sdim frag = first_frag_for_seg (s->seg); 1377218822Sdim beg = symbol_temp_new (s->seg, 0, frag); 1378218822Sdim s->text_start = beg; 1379218822Sdim 1380218822Sdim frag = last_frag_for_seg (s->seg); 1381218822Sdim end = symbol_temp_new (s->seg, get_frag_fix (frag, s->seg), frag); 1382218822Sdim s->text_end = end; 1383218822Sdim 1384218822Sdim expr.X_op = O_symbol; 1385218822Sdim expr.X_add_symbol = beg; 1386218822Sdim expr.X_add_number = 0; 1387218822Sdim emit_expr (&expr, addr_size); 1388218822Sdim 1389218822Sdim expr.X_op = O_symbol; 1390218822Sdim expr.X_add_symbol = end; 1391218822Sdim expr.X_add_number = 0; 1392218822Sdim emit_expr (&expr, addr_size); 1393218822Sdim } 1394218822Sdim 1395218822Sdim /* End of Range Entry. */ 1396218822Sdim for (i = 0; i < addr_size; i++) 1397218822Sdim out_byte (0); 1398218822Sdim for (i = 0; i < addr_size; i++) 1399218822Sdim out_byte (0); 1400218822Sdim} 1401218822Sdim 140277298Sobrien/* Emit data for .debug_aranges. */ 140377298Sobrien 140477298Sobrienstatic void 1405130561Sobrienout_debug_aranges (segT aranges_seg, segT info_seg) 140677298Sobrien{ 140777298Sobrien unsigned int addr_size = sizeof_address; 140877298Sobrien addressT size, skip; 140977298Sobrien struct line_seg *s; 141077298Sobrien expressionS expr; 141177298Sobrien char *p; 141277298Sobrien 141377298Sobrien size = 4 + 2 + 4 + 1 + 1; 141477298Sobrien 141577298Sobrien skip = 2 * addr_size - (size & (2 * addr_size - 1)); 141677298Sobrien if (skip == 2 * addr_size) 141777298Sobrien skip = 0; 141877298Sobrien size += skip; 141977298Sobrien 142077298Sobrien for (s = all_segs; s; s = s->next) 142177298Sobrien size += 2 * addr_size; 142277298Sobrien 142377298Sobrien size += 2 * addr_size; 142477298Sobrien 142577298Sobrien subseg_set (aranges_seg, 0); 142677298Sobrien 142777298Sobrien /* Length of the compilation unit. */ 142877298Sobrien out_four (size - 4); 142977298Sobrien 143077298Sobrien /* Version. */ 143177298Sobrien out_two (2); 143277298Sobrien 143377298Sobrien /* Offset to .debug_info. */ 1434130561Sobrien /* ??? sizeof_offset */ 1435130561Sobrien TC_DWARF2_EMIT_OFFSET (section_symbol (info_seg), 4); 143677298Sobrien 143777298Sobrien /* Size of an address (offset portion). */ 143877298Sobrien out_byte (addr_size); 143977298Sobrien 144077298Sobrien /* Size of a segment descriptor. */ 144177298Sobrien out_byte (0); 144277298Sobrien 144377298Sobrien /* Align the header. */ 144477298Sobrien if (skip) 144577298Sobrien frag_align (ffs (2 * addr_size) - 1, 0, 0); 144677298Sobrien 144777298Sobrien for (s = all_segs; s; s = s->next) 144860484Sobrien { 144977298Sobrien fragS *frag; 145077298Sobrien symbolS *beg, *end; 145160484Sobrien 145277298Sobrien frag = first_frag_for_seg (s->seg); 1453130561Sobrien beg = symbol_temp_new (s->seg, 0, frag); 145477298Sobrien s->text_start = beg; 145560484Sobrien 145677298Sobrien frag = last_frag_for_seg (s->seg); 1457218822Sdim end = symbol_temp_new (s->seg, get_frag_fix (frag, s->seg), frag); 145877298Sobrien s->text_end = end; 145960484Sobrien 146077298Sobrien expr.X_op = O_symbol; 146177298Sobrien expr.X_add_symbol = beg; 146277298Sobrien expr.X_add_number = 0; 146377298Sobrien emit_expr (&expr, addr_size); 146477298Sobrien 146577298Sobrien expr.X_op = O_subtract; 146677298Sobrien expr.X_add_symbol = end; 146777298Sobrien expr.X_op_symbol = beg; 146877298Sobrien expr.X_add_number = 0; 146977298Sobrien emit_expr (&expr, addr_size); 147060484Sobrien } 147160484Sobrien 147277298Sobrien p = frag_more (2 * addr_size); 147377298Sobrien md_number_to_chars (p, 0, addr_size); 147477298Sobrien md_number_to_chars (p + addr_size, 0, addr_size); 147577298Sobrien} 147660484Sobrien 147777298Sobrien/* Emit data for .debug_abbrev. Note that this must be kept in 147877298Sobrien sync with out_debug_info below. */ 147960484Sobrien 148077298Sobrienstatic void 1481130561Sobrienout_debug_abbrev (segT abbrev_seg) 148277298Sobrien{ 148377298Sobrien subseg_set (abbrev_seg, 0); 148477298Sobrien 148577298Sobrien out_uleb128 (1); 148677298Sobrien out_uleb128 (DW_TAG_compile_unit); 148777298Sobrien out_byte (DW_CHILDREN_no); 148877298Sobrien out_abbrev (DW_AT_stmt_list, DW_FORM_data4); 148977298Sobrien if (all_segs->next == NULL) 149060484Sobrien { 149177298Sobrien out_abbrev (DW_AT_low_pc, DW_FORM_addr); 149277298Sobrien out_abbrev (DW_AT_high_pc, DW_FORM_addr); 149360484Sobrien } 1494218822Sdim else 1495218822Sdim { 1496218822Sdim if (DWARF2_FORMAT () == dwarf2_format_32bit) 1497218822Sdim out_abbrev (DW_AT_ranges, DW_FORM_data4); 1498218822Sdim else 1499218822Sdim out_abbrev (DW_AT_ranges, DW_FORM_data8); 1500218822Sdim } 1501104834Sobrien out_abbrev (DW_AT_name, DW_FORM_string); 150277298Sobrien out_abbrev (DW_AT_comp_dir, DW_FORM_string); 150377298Sobrien out_abbrev (DW_AT_producer, DW_FORM_string); 150477298Sobrien out_abbrev (DW_AT_language, DW_FORM_data2); 150577298Sobrien out_abbrev (0, 0); 150677298Sobrien 150777298Sobrien /* Terminate the abbreviations for this compilation unit. */ 150877298Sobrien out_byte (0); 150960484Sobrien} 151060484Sobrien 151177298Sobrien/* Emit a description of this compilation unit for .debug_info. */ 151277298Sobrien 151377298Sobrienstatic void 1514218822Sdimout_debug_info (segT info_seg, segT abbrev_seg, segT line_seg, segT ranges_seg) 151560484Sobrien{ 151677298Sobrien char producer[128]; 151777298Sobrien char *comp_dir; 151877298Sobrien expressionS expr; 151977298Sobrien symbolS *info_start; 152077298Sobrien symbolS *info_end; 152177298Sobrien char *p; 152277298Sobrien int len; 1523130561Sobrien enum dwarf2_format d2f; 1524130561Sobrien int sizeof_offset; 152560484Sobrien 152677298Sobrien subseg_set (info_seg, 0); 152760484Sobrien 1528130561Sobrien info_start = symbol_temp_new_now (); 1529130561Sobrien info_end = symbol_temp_make (); 153060484Sobrien 153177298Sobrien /* Compilation Unit length. */ 153277298Sobrien expr.X_op = O_subtract; 153377298Sobrien expr.X_add_symbol = info_end; 153477298Sobrien expr.X_op_symbol = info_start; 153560484Sobrien 1536130561Sobrien d2f = DWARF2_FORMAT (); 1537130561Sobrien if (d2f == dwarf2_format_32bit) 1538130561Sobrien { 1539130561Sobrien expr.X_add_number = -4; 1540130561Sobrien emit_expr (&expr, 4); 1541130561Sobrien sizeof_offset = 4; 1542130561Sobrien } 1543130561Sobrien else if (d2f == dwarf2_format_64bit) 1544130561Sobrien { 1545130561Sobrien expr.X_add_number = -12; 1546130561Sobrien out_four (-1); 1547130561Sobrien emit_expr (&expr, 8); 1548130561Sobrien sizeof_offset = 8; 1549130561Sobrien } 1550130561Sobrien else if (d2f == dwarf2_format_64bit_irix) 1551130561Sobrien { 1552130561Sobrien expr.X_add_number = -8; 1553130561Sobrien emit_expr (&expr, 8); 1554130561Sobrien sizeof_offset = 8; 1555130561Sobrien } 1556130561Sobrien else 1557130561Sobrien { 1558130561Sobrien as_fatal (_("internal error: unknown dwarf2 format")); 1559130561Sobrien } 1560130561Sobrien 156177298Sobrien /* DWARF version. */ 156277298Sobrien out_two (2); 156360484Sobrien 156477298Sobrien /* .debug_abbrev offset */ 1565130561Sobrien TC_DWARF2_EMIT_OFFSET (section_symbol (abbrev_seg), sizeof_offset); 156660484Sobrien 156777298Sobrien /* Target address size. */ 156877298Sobrien out_byte (sizeof_address); 156960484Sobrien 157077298Sobrien /* DW_TAG_compile_unit DIE abbrev */ 157177298Sobrien out_uleb128 (1); 157260484Sobrien 157377298Sobrien /* DW_AT_stmt_list */ 1574130561Sobrien /* ??? sizeof_offset */ 1575130561Sobrien TC_DWARF2_EMIT_OFFSET (section_symbol (line_seg), 4); 157660484Sobrien 1577218822Sdim /* These two attributes are emitted if all of the code is contiguous. */ 157877298Sobrien if (all_segs->next == NULL) 157977298Sobrien { 158077298Sobrien /* DW_AT_low_pc */ 158177298Sobrien expr.X_op = O_symbol; 158277298Sobrien expr.X_add_symbol = all_segs->text_start; 158377298Sobrien expr.X_add_number = 0; 158477298Sobrien emit_expr (&expr, sizeof_address); 158560484Sobrien 158677298Sobrien /* DW_AT_high_pc */ 158777298Sobrien expr.X_op = O_symbol; 158877298Sobrien expr.X_add_symbol = all_segs->text_end; 158977298Sobrien expr.X_add_number = 0; 159077298Sobrien emit_expr (&expr, sizeof_address); 159177298Sobrien } 1592218822Sdim else 1593218822Sdim { 1594218822Sdim /* This attribute is emitted if the code is disjoint. */ 1595218822Sdim /* DW_AT_ranges. */ 1596218822Sdim TC_DWARF2_EMIT_OFFSET (section_symbol (ranges_seg), sizeof_offset); 1597218822Sdim } 159860484Sobrien 1599104834Sobrien /* DW_AT_name. We don't have the actual file name that was present 1600104834Sobrien on the command line, so assume files[1] is the main input file. 1601104834Sobrien We're not supposed to get called unless at least one line number 1602104834Sobrien entry was emitted, so this should always be defined. */ 1603104834Sobrien if (!files || files_in_use < 1) 1604104834Sobrien abort (); 1605130561Sobrien if (files[1].dir) 1606130561Sobrien { 1607130561Sobrien len = strlen (dirs[files[1].dir]); 1608130561Sobrien p = frag_more (len + 1); 1609130561Sobrien memcpy (p, dirs[files[1].dir], len); 1610218822Sdim INSERT_DIR_SEPARATOR (p, len); 1611130561Sobrien } 1612104834Sobrien len = strlen (files[1].filename) + 1; 1613104834Sobrien p = frag_more (len); 1614104834Sobrien memcpy (p, files[1].filename, len); 1615104834Sobrien 161677298Sobrien /* DW_AT_comp_dir */ 161777298Sobrien comp_dir = getpwd (); 161877298Sobrien len = strlen (comp_dir) + 1; 161977298Sobrien p = frag_more (len); 162077298Sobrien memcpy (p, comp_dir, len); 162177298Sobrien 162277298Sobrien /* DW_AT_producer */ 162377298Sobrien sprintf (producer, "GNU AS %s", VERSION); 162477298Sobrien len = strlen (producer) + 1; 162577298Sobrien p = frag_more (len); 162677298Sobrien memcpy (p, producer, len); 162777298Sobrien 162877298Sobrien /* DW_AT_language. Yes, this is probably not really MIPS, but the 162977298Sobrien dwarf2 draft has no standard code for assembler. */ 163077298Sobrien out_two (DW_LANG_Mips_Assembler); 163177298Sobrien 1632130561Sobrien symbol_set_value_now (info_end); 163360484Sobrien} 163460484Sobrien 1635218822Sdim/* Finish the dwarf2 debug sections. We emit .debug.line if there 1636218822Sdim were any .file/.loc directives, or --gdwarf2 was given, or if the 1637218822Sdim file has a non-empty .debug_info section. If we emit .debug_line, 1638218822Sdim and the .debug_info section is empty, we also emit .debug_info, 1639218822Sdim .debug_aranges and .debug_abbrev. ALL_SEGS will be non-null if 1640218822Sdim there were any .file/.loc directives, or --gdwarf2 was given and 1641218822Sdim there were any located instructions emitted. */ 1642218822Sdim 164360484Sobrienvoid 1644130561Sobriendwarf2_finish (void) 164560484Sobrien{ 164677298Sobrien segT line_seg; 164777298Sobrien struct line_seg *s; 1648218822Sdim segT info_seg; 1649218822Sdim int emit_other_sections = 0; 165060484Sobrien 1651218822Sdim info_seg = bfd_get_section_by_name (stdoutput, ".debug_info"); 1652218822Sdim emit_other_sections = info_seg == NULL || !seg_not_empty_p (info_seg); 1653218822Sdim 1654218822Sdim if (!all_segs && emit_other_sections) 1655218822Sdim /* There is no line information and no non-empty .debug_info 1656218822Sdim section. */ 165777298Sobrien return; 165877298Sobrien 165977298Sobrien /* Calculate the size of an address for the target machine. */ 1660130561Sobrien sizeof_address = DWARF2_ADDR_SIZE (stdoutput); 166177298Sobrien 166277298Sobrien /* Create and switch to the line number section. */ 166377298Sobrien line_seg = subseg_new (".debug_line", 0); 1664218822Sdim bfd_set_section_flags (stdoutput, line_seg, SEC_READONLY | SEC_DEBUGGING); 166577298Sobrien 166677298Sobrien /* For each subsection, chain the debug entries together. */ 166777298Sobrien for (s = all_segs; s; s = s->next) 166860484Sobrien { 166977298Sobrien struct line_subseg *ss = s->head; 167077298Sobrien struct line_entry **ptail = ss->ptail; 167177298Sobrien 167277298Sobrien while ((ss = ss->next) != NULL) 167377298Sobrien { 167477298Sobrien *ptail = ss->head; 167577298Sobrien ptail = ss->ptail; 167677298Sobrien } 167760484Sobrien } 167860484Sobrien 167977298Sobrien out_debug_line (line_seg); 168060484Sobrien 1681218822Sdim /* If this is assembler generated line info, and there is no 1682218822Sdim debug_info already, we need .debug_info and .debug_abbrev 1683218822Sdim sections as well. */ 1684218822Sdim if (emit_other_sections) 168577298Sobrien { 168677298Sobrien segT abbrev_seg; 168777298Sobrien segT aranges_seg; 1688218822Sdim segT ranges_seg; 168960484Sobrien 1690218822Sdim assert (all_segs); 1691218822Sdim 169277298Sobrien info_seg = subseg_new (".debug_info", 0); 169377298Sobrien abbrev_seg = subseg_new (".debug_abbrev", 0); 169477298Sobrien aranges_seg = subseg_new (".debug_aranges", 0); 169560484Sobrien 1696218822Sdim bfd_set_section_flags (stdoutput, info_seg, 1697218822Sdim SEC_READONLY | SEC_DEBUGGING); 1698218822Sdim bfd_set_section_flags (stdoutput, abbrev_seg, 1699218822Sdim SEC_READONLY | SEC_DEBUGGING); 1700218822Sdim bfd_set_section_flags (stdoutput, aranges_seg, 1701218822Sdim SEC_READONLY | SEC_DEBUGGING); 170277298Sobrien 170377298Sobrien record_alignment (aranges_seg, ffs (2 * sizeof_address) - 1); 170477298Sobrien 1705218822Sdim if (all_segs->next == NULL) 1706218822Sdim ranges_seg = NULL; 1707218822Sdim else 1708218822Sdim { 1709218822Sdim ranges_seg = subseg_new (".debug_ranges", 0); 1710218822Sdim bfd_set_section_flags (stdoutput, ranges_seg, 1711218822Sdim SEC_READONLY | SEC_DEBUGGING); 1712218822Sdim record_alignment (ranges_seg, ffs (2 * sizeof_address) - 1); 1713218822Sdim out_debug_ranges (ranges_seg); 1714218822Sdim } 1715218822Sdim 171677298Sobrien out_debug_aranges (aranges_seg, info_seg); 171777298Sobrien out_debug_abbrev (abbrev_seg); 1718218822Sdim out_debug_info (info_seg, abbrev_seg, line_seg, ranges_seg); 171977298Sobrien } 172060484Sobrien} 1721