dwarf2dbg.c revision 77298
160484Sobrien/* dwarf2dbg.c - DWARF2 debug support
260484Sobrien   Copyright (C) 1999, 2000 Free Software Foundation, Inc.
360484Sobrien   Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
460484Sobrien
560484Sobrien   This file is part of GAS, the GNU Assembler.
660484Sobrien
760484Sobrien   GAS is free software; you can redistribute it and/or modify
860484Sobrien   it under the terms of the GNU General Public License as published by
960484Sobrien   the Free Software Foundation; either version 2, or (at your option)
1060484Sobrien   any later version.
1160484Sobrien
1260484Sobrien   GAS is distributed in the hope that it will be useful,
1360484Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1460484Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1560484Sobrien   GNU General Public License for more details.
1660484Sobrien
1760484Sobrien   You should have received a copy of the GNU General Public License
1860484Sobrien   along with GAS; see the file COPYING.  If not, write to the Free
1960484Sobrien   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2060484Sobrien   02111-1307, USA.  */
2160484Sobrien
2260484Sobrien/* Logical line numbers can be controlled by the compiler via the
2360484Sobrien   following two directives:
2460484Sobrien
2560484Sobrien	.file FILENO "file.c"
2660484Sobrien	.loc  FILENO LINENO [COLUMN]
2760484Sobrien
2860484Sobrien   FILENO is the filenumber.  */
2960484Sobrien
3060484Sobrien#include "ansidecl.h"
3177298Sobrien#include "as.h"
3260484Sobrien
3377298Sobrien#ifdef HAVE_LIMITS_H
3477298Sobrien#include <limits.h>
3577298Sobrien#else
3677298Sobrien#ifdef HAVE_SYS_PARAM_H
3777298Sobrien#include <sys/param.h>
3877298Sobrien#endif
3977298Sobrien#ifndef INT_MAX
4077298Sobrien#define INT_MAX (int) (((unsigned) (-1)) >> 1)
4177298Sobrien#endif
4277298Sobrien#endif
4377298Sobrien
4477298Sobrien#ifdef BFD_ASSEMBLER
4577298Sobrien
4660484Sobrien#include "dwarf2dbg.h"
4760484Sobrien#include "subsegs.h"
4860484Sobrien
4960484Sobrien#include "elf/dwarf2.h"
5060484Sobrien
5160484Sobrien/* Since we can't generate the prolog until the body is complete, we
5260484Sobrien   use three different subsegments for .debug_line: one holding the
5360484Sobrien   prolog, one for the directory and filename info, and one for the
5460484Sobrien   body ("statement program").  */
5560484Sobrien#define DL_PROLOG	0
5660484Sobrien#define DL_FILES	1
5760484Sobrien#define DL_BODY		2
5860484Sobrien
5960484Sobrien/* First special line opcde - leave room for the standard opcodes.
6060484Sobrien   Note: If you want to change this, you'll have to update the
6160484Sobrien   "standard_opcode_lengths" table that is emitted below in
6260484Sobrien   dwarf2_finish().  */
6360484Sobrien#define DWARF2_LINE_OPCODE_BASE		10
6460484Sobrien
6560484Sobrien#ifndef DWARF2_LINE_BASE
6660484Sobrien  /* Minimum line offset in a special line info. opcode.  This value
6760484Sobrien     was chosen to give a reasonable range of values.  */
6860484Sobrien# define DWARF2_LINE_BASE		-5
6960484Sobrien#endif
7060484Sobrien
7160484Sobrien/* Range of line offsets in a special line info. opcode.  */
7260484Sobrien#ifndef DWARF2_LINE_RANGE
7360484Sobrien# define DWARF2_LINE_RANGE		14
7460484Sobrien#endif
7560484Sobrien
7660484Sobrien#ifndef DWARF2_LINE_MIN_INSN_LENGTH
7760484Sobrien  /* Define the architecture-dependent minimum instruction length (in
7860484Sobrien     bytes).  This value should be rather too small than too big.  */
7977298Sobrien# define DWARF2_LINE_MIN_INSN_LENGTH	1
8060484Sobrien#endif
8160484Sobrien
8260484Sobrien/* Flag that indicates the initial value of the is_stmt_start flag.
8360484Sobrien   In the present implementation, we do not mark any lines as
8460484Sobrien   the beginning of a source statement, because that information
8560484Sobrien   is not made available by the GCC front-end.  */
8660484Sobrien#define	DWARF2_LINE_DEFAULT_IS_STMT	1
8760484Sobrien
8860484Sobrien/* Given a special op, return the line skip amount.  */
8960484Sobrien#define SPECIAL_LINE(op) \
9060484Sobrien	(((op) - DWARF2_LINE_OPCODE_BASE)%DWARF2_LINE_RANGE + DWARF2_LINE_BASE)
9160484Sobrien
9260484Sobrien/* Given a special op, return the address skip amount (in units of
9360484Sobrien   DWARF2_LINE_MIN_INSN_LENGTH.  */
9460484Sobrien#define SPECIAL_ADDR(op) (((op) - DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE)
9560484Sobrien
9660484Sobrien/* The maximum address skip amount that can be encoded with a special op.  */
9760484Sobrien#define MAX_SPECIAL_ADDR_DELTA		SPECIAL_ADDR(255)
9860484Sobrien
9977298Sobrienstruct line_entry {
10077298Sobrien  struct line_entry *next;
10177298Sobrien  fragS *frag;
10277298Sobrien  addressT frag_ofs;
10377298Sobrien  struct dwarf2_line_info loc;
10477298Sobrien};
10560484Sobrien
10677298Sobrienstruct line_subseg {
10777298Sobrien  struct line_subseg *next;
10877298Sobrien  subsegT subseg;
10977298Sobrien  struct line_entry *head;
11077298Sobrien  struct line_entry **ptail;
11177298Sobrien};
11260484Sobrien
11377298Sobrienstruct line_seg {
11477298Sobrien  struct line_seg *next;
11577298Sobrien  segT seg;
11677298Sobrien  struct line_subseg *head;
11777298Sobrien  symbolS *text_start;
11877298Sobrien  symbolS *text_end;
11977298Sobrien};
12060484Sobrien
12177298Sobrien/* Collects data for all line table entries during assembly.  */
12277298Sobrienstatic struct line_seg *all_segs;
12360484Sobrien
12477298Sobrienstruct file_entry {
12577298Sobrien  char *filename;
12677298Sobrien  unsigned int dir;
12777298Sobrien};
12860484Sobrien
12977298Sobrien/* Table of files used by .debug_line.  */
13077298Sobrienstatic struct file_entry *files;
13177298Sobrienstatic unsigned int files_in_use;
13277298Sobrienstatic unsigned int files_allocated;
13377298Sobrien
13477298Sobrien/* True when we've seen a .loc directive recently.  Used to avoid
13577298Sobrien   doing work when there's nothing to do.  */
13677298Sobrienstatic boolean loc_directive_seen;
13777298Sobrien
13877298Sobrien/* Current location as indicated by the most recent .loc directive.  */
13977298Sobrienstatic struct dwarf2_line_info current;
14077298Sobrien
14177298Sobrien/* Fake label name.  */
14277298Sobrienstatic char const fake_label_name[] = ".L0\001";
14377298Sobrien
14477298Sobrien/* The size of an address on the target.  */
14577298Sobrienstatic unsigned int sizeof_address;
14677298Sobrien
14777298Sobrienstatic struct line_subseg *get_line_subseg PARAMS ((segT, subsegT));
14877298Sobrienstatic unsigned int get_filenum PARAMS ((const char *));
14977298Sobrienstatic struct frag *first_frag_for_seg PARAMS ((segT));
15077298Sobrienstatic struct frag *last_frag_for_seg PARAMS ((segT));
15177298Sobrienstatic void out_byte PARAMS ((int));
15277298Sobrienstatic void out_opcode PARAMS ((int));
15377298Sobrienstatic void out_two PARAMS ((int));
15477298Sobrienstatic void out_four PARAMS ((int));
15577298Sobrienstatic void out_abbrev PARAMS ((int, int));
15677298Sobrienstatic void out_uleb128 PARAMS ((addressT));
15777298Sobrienstatic symbolS *symbol_new_now PARAMS ((void));
15877298Sobrienstatic void set_symbol_value_now PARAMS ((symbolS *));
15977298Sobrienstatic offsetT get_frag_fix PARAMS ((fragS *));
16077298Sobrienstatic void out_set_addr PARAMS ((segT, fragS *, addressT));
16177298Sobrienstatic int size_inc_line_addr PARAMS ((int, addressT));
16277298Sobrienstatic void emit_inc_line_addr PARAMS ((int, addressT, char *, int));
16377298Sobrienstatic void out_inc_line_addr PARAMS ((int, addressT));
16477298Sobrienstatic void relax_inc_line_addr PARAMS ((int, segT, fragS *, addressT,
16577298Sobrien					 fragS *, addressT));
16677298Sobrienstatic void process_entries PARAMS ((segT, struct line_entry *));
16777298Sobrienstatic void out_file_list PARAMS ((void));
16877298Sobrienstatic void out_debug_line PARAMS ((segT));
16977298Sobrienstatic void out_debug_aranges PARAMS ((segT, segT));
17077298Sobrienstatic void out_debug_abbrev PARAMS ((segT));
17177298Sobrienstatic void out_debug_info PARAMS ((segT, segT, segT));
17277298Sobrien
17377298Sobrien/* Find or create an entry for SEG+SUBSEG in ALL_SEGS.  */
17477298Sobrien
17577298Sobrienstatic struct line_subseg *
17677298Sobrienget_line_subseg (seg, subseg)
17777298Sobrien     segT seg;
17877298Sobrien     subsegT subseg;
17977298Sobrien{
18077298Sobrien  static segT last_seg;
18177298Sobrien  static subsegT last_subseg;
18277298Sobrien  static struct line_subseg *last_line_subseg;
18377298Sobrien
18477298Sobrien  struct line_seg *s;
18577298Sobrien  struct line_subseg **pss, *ss;
18677298Sobrien
18777298Sobrien  if (seg == last_seg && subseg == last_subseg)
18877298Sobrien    return last_line_subseg;
18977298Sobrien
19077298Sobrien  for (s = all_segs; s; s = s->next)
19177298Sobrien    if (s->seg == seg)
19277298Sobrien      goto found_seg;
19377298Sobrien
19477298Sobrien  s = (struct line_seg *) xmalloc (sizeof (*s));
19577298Sobrien  s->next = all_segs;
19677298Sobrien  s->seg = seg;
19777298Sobrien  s->head = NULL;
19877298Sobrien  all_segs = s;
19977298Sobrien
20077298Sobrien found_seg:
20177298Sobrien  for (pss = &s->head; (ss = *pss) != NULL ; pss = &ss->next)
20260484Sobrien    {
20377298Sobrien      if (ss->subseg == subseg)
20477298Sobrien	goto found_subseg;
20577298Sobrien      if (ss->subseg > subseg)
20677298Sobrien	break;
20760484Sobrien    }
20860484Sobrien
20977298Sobrien  ss = (struct line_subseg *) xmalloc (sizeof (*ss));
21077298Sobrien  ss->next = *pss;
21177298Sobrien  ss->subseg = subseg;
21277298Sobrien  ss->head = NULL;
21377298Sobrien  ss->ptail = &ss->head;
21477298Sobrien  *pss = ss;
21560484Sobrien
21677298Sobrien found_subseg:
21777298Sobrien  last_seg = seg;
21877298Sobrien  last_subseg = subseg;
21977298Sobrien  last_line_subseg = ss;
22060484Sobrien
22177298Sobrien  return ss;
22277298Sobrien}
22360484Sobrien
22477298Sobrien/* Record an entry for LOC ocurring at OFS within the current fragment.  */
22560484Sobrien
22677298Sobrienvoid
22777298Sobriendwarf2_gen_line_info (ofs, loc)
22877298Sobrien     addressT ofs;
22977298Sobrien     struct dwarf2_line_info *loc;
23060484Sobrien{
23177298Sobrien  struct line_subseg *ss;
23277298Sobrien  struct line_entry *e;
23360484Sobrien
23477298Sobrien  /* Early out for as-yet incomplete location information.  */
23577298Sobrien  if (loc->filenum == 0 || loc->line == 0)
23677298Sobrien    return;
23777298Sobrien
23877298Sobrien  e = (struct line_entry *) xmalloc (sizeof (*e));
23977298Sobrien  e->next = NULL;
24077298Sobrien  e->frag = frag_now;
24177298Sobrien  e->frag_ofs = ofs;
24277298Sobrien  e->loc = *loc;
24377298Sobrien
24477298Sobrien  ss = get_line_subseg (now_seg, now_subseg);
24577298Sobrien  *ss->ptail = e;
24677298Sobrien  ss->ptail = &e->next;
24777298Sobrien}
24877298Sobrien
24977298Sobrienvoid
25077298Sobriendwarf2_where (line)
25177298Sobrien     struct dwarf2_line_info *line;
25277298Sobrien{
25377298Sobrien  if (debug_type == DEBUG_DWARF2)
25460484Sobrien    {
25577298Sobrien      char *filename;
25677298Sobrien      as_where (&filename, &line->line);
25777298Sobrien      line->filenum = get_filenum (filename);
25877298Sobrien      line->column = 0;
25977298Sobrien      line->flags = DWARF2_FLAG_BEGIN_STMT;
26060484Sobrien    }
26177298Sobrien  else
26277298Sobrien    *line = current;
26360484Sobrien}
26460484Sobrien
26577298Sobrien/* Called for each machine instruction, or relatively atomic group of
26677298Sobrien   machine instructions (ie built-in macro).  The instruction or group
26777298Sobrien   is SIZE bytes in length.  If dwarf2 line number generation is called
26877298Sobrien   for, emit a line statement appropriately.  */
26977298Sobrien
27077298Sobrienvoid
27177298Sobriendwarf2_emit_insn (size)
27277298Sobrien     int size;
27360484Sobrien{
27477298Sobrien  struct dwarf2_line_info loc;
27560484Sobrien
27677298Sobrien  if (debug_type != DEBUG_DWARF2 && ! loc_directive_seen)
27777298Sobrien    return;
27877298Sobrien  loc_directive_seen = false;
27977298Sobrien
28077298Sobrien  dwarf2_where (&loc);
28177298Sobrien  dwarf2_gen_line_info (frag_now_fix () - size, &loc);
28277298Sobrien}
28377298Sobrien
28477298Sobrien/* Get a .debug_line file number for FILENAME.  */
28577298Sobrien
28677298Sobrienstatic unsigned int
28777298Sobrienget_filenum (filename)
28877298Sobrien     const char *filename;
28977298Sobrien{
29077298Sobrien  static unsigned int last_used;
29177298Sobrien  unsigned int i;
29277298Sobrien
29377298Sobrien  if (last_used)
29477298Sobrien    if (strcmp (filename, files[last_used].filename) == 0)
29577298Sobrien      return last_used;
29677298Sobrien
29777298Sobrien  for (i = 1; i < files_in_use; ++i)
29877298Sobrien    if (strcmp (filename, files[i].filename) == 0)
29977298Sobrien      return i;
30077298Sobrien
30177298Sobrien  if (i >= files_allocated)
30260484Sobrien    {
30377298Sobrien      unsigned int old = files_allocated;
30477298Sobrien
30577298Sobrien      files_allocated = i + 32;
30677298Sobrien      files = (struct file_entry *)
30777298Sobrien	xrealloc (files, (i + 32) * sizeof (struct file_entry));
30877298Sobrien
30977298Sobrien      memset (files + old, 0, (i + 32 - old) * sizeof (struct file_entry));
31060484Sobrien    }
31177298Sobrien
31277298Sobrien  files[i].filename = xstrdup (filename);
31377298Sobrien  files[i].dir = 0;
31477298Sobrien  files_in_use = i + 1;
31577298Sobrien  last_used = i;
31677298Sobrien
31777298Sobrien  return i;
31860484Sobrien}
31960484Sobrien
32077298Sobrien/* Handle the .file directive.  */
32177298Sobrien
32277298Sobrienvoid
32377298Sobriendwarf2_directive_file (dummy)
32477298Sobrien     int dummy ATTRIBUTE_UNUSED;
32560484Sobrien{
32677298Sobrien  offsetT num;
32777298Sobrien  const char *filename;
32877298Sobrien  int filename_len;
32960484Sobrien
33077298Sobrien  /* Continue to accept a bare string and pass it off.  */
33177298Sobrien  SKIP_WHITESPACE ();
33277298Sobrien  if (*input_line_pointer == '"')
33360484Sobrien    {
33477298Sobrien      s_app_file (0);
33577298Sobrien      return;
33660484Sobrien    }
33760484Sobrien
33877298Sobrien  num = get_absolute_expression ();
33977298Sobrien  filename = demand_copy_C_string (&filename_len);
34077298Sobrien  demand_empty_rest_of_line ();
34160484Sobrien
34277298Sobrien  if (num < 1)
34360484Sobrien    {
34477298Sobrien      as_bad (_("File number less than one"));
34560484Sobrien      return;
34660484Sobrien    }
34760484Sobrien
34877298Sobrien  if (num < files_in_use && files[num].filename != 0)
34960484Sobrien    {
35077298Sobrien      as_bad (_("File number %d already allocated"), num);
35160484Sobrien      return;
35260484Sobrien    }
35360484Sobrien
35477298Sobrien  if (num >= (int) files_allocated)
35577298Sobrien    {
35677298Sobrien      unsigned int old = files_allocated;
35760484Sobrien
35877298Sobrien      files_allocated = num + 16;
35977298Sobrien      files = (struct file_entry *)
36077298Sobrien	xrealloc (files, (num + 16) * sizeof (struct file_entry));
36177298Sobrien
36277298Sobrien      /* Zero the new memory.  */
36377298Sobrien      memset (files + old, 0, (num + 16 - old) * sizeof (struct file_entry));
36477298Sobrien    }
36577298Sobrien
36677298Sobrien  files[num].filename = filename;
36777298Sobrien  files[num].dir = 0;
36877298Sobrien  files_in_use = num + 1;
36960484Sobrien}
37060484Sobrien
37177298Sobrienvoid
37277298Sobriendwarf2_directive_loc (dummy)
37377298Sobrien     int dummy ATTRIBUTE_UNUSED;
37477298Sobrien{
37577298Sobrien  offsetT filenum, line, column;
37677298Sobrien
37777298Sobrien  filenum = get_absolute_expression ();
37877298Sobrien  SKIP_WHITESPACE ();
37977298Sobrien  line = get_absolute_expression ();
38077298Sobrien  SKIP_WHITESPACE ();
38177298Sobrien  column = get_absolute_expression ();
38277298Sobrien  demand_empty_rest_of_line ();
38377298Sobrien
38477298Sobrien  if (filenum < 1)
38577298Sobrien    {
38677298Sobrien      as_bad (_("File number less than one"));
38777298Sobrien      return;
38877298Sobrien    }
38977298Sobrien  if (filenum >= (int) files_in_use || files[filenum].filename == 0)
39077298Sobrien    {
39177298Sobrien      as_bad (_("Unassigned file number %ld"), (long) filenum);
39277298Sobrien      return;
39377298Sobrien    }
39477298Sobrien
39577298Sobrien  current.filenum = filenum;
39677298Sobrien  current.line = line;
39777298Sobrien  current.column = column;
39877298Sobrien  current.flags = DWARF2_FLAG_BEGIN_STMT;
39977298Sobrien
40077298Sobrien  loc_directive_seen = true;
40177298Sobrien
40277298Sobrien#ifndef NO_LISTING
40377298Sobrien  if (listing)
40477298Sobrien    listing_source_line (line);
40577298Sobrien#endif
40677298Sobrien}
40777298Sobrien
40877298Sobrienstatic struct frag *
40977298Sobrienfirst_frag_for_seg (seg)
41077298Sobrien     segT seg;
41177298Sobrien{
41277298Sobrien  frchainS *f, *first = NULL;
41377298Sobrien
41477298Sobrien  for (f = frchain_root; f; f = f->frch_next)
41577298Sobrien    if (f->frch_seg == seg
41677298Sobrien	&& (! first || first->frch_subseg > f->frch_subseg))
41777298Sobrien      first = f;
41877298Sobrien
41977298Sobrien  return first ? first->frch_root : NULL;
42077298Sobrien}
42177298Sobrien
42277298Sobrienstatic struct frag *
42377298Sobrienlast_frag_for_seg (seg)
42477298Sobrien     segT seg;
42577298Sobrien{
42677298Sobrien  frchainS *f, *last = NULL;
42777298Sobrien
42877298Sobrien  for (f = frchain_root; f; f = f->frch_next)
42977298Sobrien    if (f->frch_seg == seg
43077298Sobrien	&& (! last || last->frch_subseg < f->frch_subseg))
43177298Sobrien      last= f;
43277298Sobrien
43377298Sobrien  return last ? last->frch_last : NULL;
43477298Sobrien}
43577298Sobrien
43677298Sobrien/* Emit a single byte into the current segment.  */
43777298Sobrien
43877298Sobrienstatic inline void
43977298Sobrienout_byte (byte)
44077298Sobrien     int byte;
44177298Sobrien{
44277298Sobrien  FRAG_APPEND_1_CHAR (byte);
44377298Sobrien}
44477298Sobrien
44577298Sobrien/* Emit a statement program opcode into the current segment.  */
44677298Sobrien
44777298Sobrienstatic inline void
44877298Sobrienout_opcode (opc)
44977298Sobrien     int opc;
45077298Sobrien{
45177298Sobrien  out_byte (opc);
45277298Sobrien}
45377298Sobrien
45477298Sobrien/* Emit a two-byte word into the current segment.  */
45577298Sobrien
45677298Sobrienstatic inline void
45777298Sobrienout_two (data)
45877298Sobrien     int data;
45977298Sobrien{
46077298Sobrien  md_number_to_chars (frag_more (2), data, 2);
46177298Sobrien}
46277298Sobrien
46377298Sobrien/* Emit a four byte word into the current segment.  */
46477298Sobrien
46577298Sobrienstatic inline void
46677298Sobrienout_four (data)
46777298Sobrien     int data;
46877298Sobrien{
46977298Sobrien  md_number_to_chars (frag_more (4), data, 4);
47077298Sobrien}
47177298Sobrien
47277298Sobrien/* Emit an unsigned "little-endian base 128" number.  */
47377298Sobrien
47460484Sobrienstatic void
47577298Sobrienout_uleb128 (value)
47677298Sobrien     addressT value;
47760484Sobrien{
47877298Sobrien  output_leb128 (frag_more (sizeof_leb128 (value, 0)), value, 0);
47977298Sobrien}
48060484Sobrien
48177298Sobrien/* Emit a tuple for .debug_abbrev.  */
48277298Sobrien
48377298Sobrienstatic inline void
48477298Sobrienout_abbrev (name, form)
48577298Sobrien     int name, form;
48677298Sobrien{
48777298Sobrien  out_uleb128 (name);
48877298Sobrien  out_uleb128 (form);
48960484Sobrien}
49060484Sobrien
49177298Sobrien/* Create a new fake symbol whose value is the current position.  */
49277298Sobrien
49377298Sobrienstatic symbolS *
49477298Sobriensymbol_new_now ()
49577298Sobrien{
49677298Sobrien  return symbol_new (fake_label_name, now_seg, frag_now_fix (), frag_now);
49777298Sobrien}
49877298Sobrien
49977298Sobrien/* Set the value of SYM to the current position in the current segment.  */
50077298Sobrien
50160484Sobrienstatic void
50277298Sobrienset_symbol_value_now (sym)
50377298Sobrien     symbolS *sym;
50460484Sobrien{
50577298Sobrien  S_SET_SEGMENT (sym, now_seg);
50677298Sobrien  S_SET_VALUE (sym, frag_now_fix ());
50777298Sobrien  symbol_set_frag (sym, frag_now);
50877298Sobrien}
50960484Sobrien
51077298Sobrien/* Get the size of a fragment.  */
51160484Sobrien
51277298Sobrienstatic offsetT
51377298Sobrienget_frag_fix (frag)
51477298Sobrien     fragS *frag;
51577298Sobrien{
51677298Sobrien  frchainS *fr;
51760484Sobrien
51877298Sobrien  if (frag->fr_next)
51977298Sobrien    return frag->fr_fix;
52060484Sobrien
52177298Sobrien  /* If a fragment is the last in the chain, special measures must be
52277298Sobrien     taken to find its size before relaxation, since it may be pending
52377298Sobrien     on some subsegment chain.  */
52477298Sobrien  for (fr = frchain_root; fr; fr = fr->frch_next)
52577298Sobrien    if (fr->frch_last == frag)
52677298Sobrien      {
52777298Sobrien	return ((char *) obstack_next_free (&fr->frch_obstack)
52877298Sobrien		- frag->fr_literal);
52977298Sobrien      }
53060484Sobrien
53177298Sobrien  abort ();
53277298Sobrien}
53377298Sobrien
53477298Sobrien/* Set an absolute address (may result in a relocation entry).  */
53577298Sobrien
53677298Sobrienstatic void
53777298Sobrienout_set_addr (seg, frag, ofs)
53877298Sobrien     segT seg;
53977298Sobrien     fragS *frag;
54077298Sobrien     addressT ofs;
54177298Sobrien{
54277298Sobrien  expressionS expr;
54377298Sobrien  symbolS *sym;
54477298Sobrien
54577298Sobrien  sym = symbol_new (fake_label_name, seg, ofs, frag);
54677298Sobrien
54760484Sobrien  out_opcode (DW_LNS_extended_op);
54877298Sobrien  out_uleb128 (sizeof_address + 1);
54960484Sobrien
55060484Sobrien  out_opcode (DW_LNE_set_address);
55160484Sobrien  expr.X_op = O_symbol;
55260484Sobrien  expr.X_add_symbol = sym;
55360484Sobrien  expr.X_add_number = 0;
55477298Sobrien  emit_expr (&expr, sizeof_address);
55560484Sobrien}
55660484Sobrien
55777298Sobrien/* Encode a pair of line and address skips as efficiently as possible.
55877298Sobrien   Note that the line skip is signed, whereas the address skip is unsigned.
55977298Sobrien
56077298Sobrien   The following two routines *must* be kept in sync.  This is
56177298Sobrien   enforced by making emit_inc_line_addr abort if we do not emit
56277298Sobrien   exactly the expected number of bytes.  */
56377298Sobrien
56477298Sobrienstatic int
56577298Sobriensize_inc_line_addr (line_delta, addr_delta)
56677298Sobrien     int line_delta;
56777298Sobrien     addressT addr_delta;
56860484Sobrien{
56977298Sobrien  unsigned int tmp, opcode;
57077298Sobrien  int len = 0;
57160484Sobrien
57277298Sobrien  /* Scale the address delta by the minimum instruction length.  */
57377298Sobrien#if DWARF2_LINE_MIN_INSN_LENGTH > 1
57477298Sobrien  assert (addr_delta % DWARF2_LINE_MIN_INSN_LENGTH == 0);
57577298Sobrien  addr_delta /= DWARF2_LINE_MIN_INSN_LENGTH;
57677298Sobrien#endif
57777298Sobrien
57877298Sobrien  /* INT_MAX is a signal that this is actually a DW_LNE_end_sequence.
57977298Sobrien     We cannot use special opcodes here, since we want the end_sequence
58077298Sobrien     to emit the matrix entry.  */
58177298Sobrien  if (line_delta == INT_MAX)
58260484Sobrien    {
58377298Sobrien      if (addr_delta == MAX_SPECIAL_ADDR_DELTA)
58477298Sobrien	len = 1;
58560484Sobrien      else
58677298Sobrien	len = 1 + sizeof_leb128 (addr_delta, 0);
58777298Sobrien      return len + 3;
58860484Sobrien    }
58960484Sobrien
59077298Sobrien  /* Bias the line delta by the base.  */
59177298Sobrien  tmp = line_delta - DWARF2_LINE_BASE;
59260484Sobrien
59377298Sobrien  /* If the line increment is out of range of a special opcode, we
59477298Sobrien     must encode it with DW_LNS_advance_line.  */
59577298Sobrien  if (tmp >= DWARF2_LINE_RANGE)
59677298Sobrien    {
59777298Sobrien      len = 1 + sizeof_leb128 (line_delta, 1);
59877298Sobrien      line_delta = 0;
59977298Sobrien      tmp = 0 - DWARF2_LINE_BASE;
60077298Sobrien    }
60177298Sobrien
60277298Sobrien  /* Bias the opcode by the special opcode base.  */
60377298Sobrien  tmp += DWARF2_LINE_OPCODE_BASE;
60477298Sobrien
60577298Sobrien  /* Avoid overflow when addr_delta is large.  */
60677298Sobrien  if (addr_delta < 256 + MAX_SPECIAL_ADDR_DELTA)
60777298Sobrien    {
60877298Sobrien      /* Try using a special opcode.  */
60977298Sobrien      opcode = tmp + addr_delta * DWARF2_LINE_RANGE;
61077298Sobrien      if (opcode <= 255)
61177298Sobrien	return len + 1;
61277298Sobrien
61377298Sobrien      /* Try using DW_LNS_const_add_pc followed by special op.  */
61477298Sobrien      opcode = tmp + (addr_delta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE;
61577298Sobrien      if (opcode <= 255)
61677298Sobrien	return len + 2;
61777298Sobrien    }
61877298Sobrien
61977298Sobrien  /* Otherwise use DW_LNS_advance_pc.  */
62077298Sobrien  len += 1 + sizeof_leb128 (addr_delta, 0);
62177298Sobrien
62277298Sobrien  /* DW_LNS_copy or special opcode.  */
62377298Sobrien  len += 1;
62477298Sobrien
62577298Sobrien  return len;
62660484Sobrien}
62760484Sobrien
62877298Sobrienstatic void
62977298Sobrienemit_inc_line_addr (line_delta, addr_delta, p, len)
63077298Sobrien     int line_delta;
63177298Sobrien     addressT addr_delta;
63277298Sobrien     char *p;
63377298Sobrien     int len;
63460484Sobrien{
63577298Sobrien  unsigned int tmp, opcode;
63677298Sobrien  int need_copy = 0;
63777298Sobrien  char *end = p + len;
63860484Sobrien
63977298Sobrien#if DWARF2_LINE_MIN_INSN_LENGTH > 1
64077298Sobrien  /* Scale the address delta by the minimum instruction length.  */
64177298Sobrien  assert (addr_delta % DWARF2_LINE_MIN_INSN_LENGTH == 0);
64277298Sobrien  addr_delta /= DWARF2_LINE_MIN_INSN_LENGTH;
64377298Sobrien#endif
64477298Sobrien  /* INT_MAX is a signal that this is actually a DW_LNE_end_sequence.
64577298Sobrien     We cannot use special opcodes here, since we want the end_sequence
64677298Sobrien     to emit the matrix entry.  */
64777298Sobrien  if (line_delta == INT_MAX)
64860484Sobrien    {
64977298Sobrien      if (addr_delta == MAX_SPECIAL_ADDR_DELTA)
65077298Sobrien	*p++ = DW_LNS_const_add_pc;
65177298Sobrien      else
65260484Sobrien	{
65377298Sobrien	  *p++ = DW_LNS_advance_pc;
65477298Sobrien	  p += output_leb128 (p, addr_delta, 0);
65560484Sobrien	}
65677298Sobrien
65777298Sobrien      *p++ = DW_LNS_extended_op;
65877298Sobrien      *p++ = 1;
65977298Sobrien      *p++ = DW_LNE_end_sequence;
66077298Sobrien      goto done;
66160484Sobrien    }
66260484Sobrien
66377298Sobrien  /* Bias the line delta by the base.  */
66477298Sobrien  tmp = line_delta - DWARF2_LINE_BASE;
66577298Sobrien
66677298Sobrien  /* If the line increment is out of range of a special opcode, we
66777298Sobrien     must encode it with DW_LNS_advance_line.  */
66877298Sobrien  if (tmp >= DWARF2_LINE_RANGE)
66960484Sobrien    {
67077298Sobrien      *p++ = DW_LNS_advance_line;
67177298Sobrien      p += output_leb128 (p, line_delta, 1);
67260484Sobrien
67377298Sobrien      /* Prettier, I think, to use DW_LNS_copy instead of a
67477298Sobrien	 "line +0, addr +0" special opcode.  */
67577298Sobrien      if (addr_delta == 0)
67677298Sobrien	{
67777298Sobrien	  *p++ = DW_LNS_copy;
67877298Sobrien	  goto done;
67977298Sobrien	}
68060484Sobrien
68177298Sobrien      line_delta = 0;
68277298Sobrien      tmp = 0 - DWARF2_LINE_BASE;
68377298Sobrien      need_copy = 1;
68477298Sobrien    }
68560484Sobrien
68677298Sobrien  /* Bias the opcode by the special opcode base.  */
68777298Sobrien  tmp += DWARF2_LINE_OPCODE_BASE;
68860484Sobrien
68977298Sobrien  /* Avoid overflow when addr_delta is large.  */
69077298Sobrien  if (addr_delta < 256 + MAX_SPECIAL_ADDR_DELTA)
69160484Sobrien    {
69277298Sobrien      /* Try using a special opcode.  */
69377298Sobrien      opcode = tmp + addr_delta * DWARF2_LINE_RANGE;
69477298Sobrien      if (opcode <= 255)
69560484Sobrien	{
69677298Sobrien	  *p++ = opcode;
69777298Sobrien	  goto done;
69860484Sobrien	}
69977298Sobrien
70077298Sobrien      /* Try using DW_LNS_const_add_pc followed by special op.  */
70177298Sobrien      opcode = tmp + (addr_delta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE;
70277298Sobrien      if (opcode <= 255)
70377298Sobrien	{
70477298Sobrien	  *p++ = DW_LNS_const_add_pc;
70577298Sobrien	  *p++ = opcode;
70677298Sobrien	  goto done;
70777298Sobrien	}
70860484Sobrien    }
70977298Sobrien
71077298Sobrien  /* Otherwise use DW_LNS_advance_pc.  */
71177298Sobrien  *p++ = DW_LNS_advance_pc;
71277298Sobrien  p += output_leb128 (p, addr_delta, 0);
71377298Sobrien
71477298Sobrien  if (need_copy)
71577298Sobrien    *p++ = DW_LNS_copy;
71660484Sobrien  else
71777298Sobrien    *p++ = tmp;
71860484Sobrien
71977298Sobrien done:
72077298Sobrien  assert (p == end);
72177298Sobrien}
72260484Sobrien
72377298Sobrien/* Handy routine to combine calls to the above two routines.  */
72460484Sobrien
72577298Sobrienstatic void
72677298Sobrienout_inc_line_addr (line_delta, addr_delta)
72777298Sobrien     int line_delta;
72877298Sobrien     addressT addr_delta;
72977298Sobrien{
73077298Sobrien  int len = size_inc_line_addr (line_delta, addr_delta);
73177298Sobrien  emit_inc_line_addr (line_delta, addr_delta, frag_more (len), len);
73277298Sobrien}
73360484Sobrien
73477298Sobrien/* Generate a variant frag that we can use to relax address/line
73577298Sobrien   increments between fragments of the target segment.  */
73660484Sobrien
73777298Sobrienstatic void
73877298Sobrienrelax_inc_line_addr (line_delta, seg, to_frag, to_ofs, from_frag, from_ofs)
73977298Sobrien     int line_delta;
74077298Sobrien     segT seg;
74177298Sobrien     fragS *to_frag, *from_frag;
74277298Sobrien     addressT to_ofs, from_ofs;
74377298Sobrien{
74477298Sobrien  symbolS *to_sym, *from_sym;
74577298Sobrien  expressionS expr;
74677298Sobrien  int max_chars;
74760484Sobrien
74877298Sobrien  to_sym = symbol_new (fake_label_name, seg, to_ofs, to_frag);
74977298Sobrien  from_sym = symbol_new (fake_label_name, seg, from_ofs, from_frag);
75060484Sobrien
75177298Sobrien  expr.X_op = O_subtract;
75277298Sobrien  expr.X_add_symbol = to_sym;
75377298Sobrien  expr.X_op_symbol = from_sym;
75477298Sobrien  expr.X_add_number = 0;
75560484Sobrien
75677298Sobrien  /* The maximum size of the frag is the line delta with a maximum
75777298Sobrien     sized address delta.  */
75877298Sobrien  max_chars = size_inc_line_addr (line_delta, -DWARF2_LINE_MIN_INSN_LENGTH);
75960484Sobrien
76077298Sobrien  frag_var (rs_dwarf2dbg, max_chars, max_chars, 1,
76177298Sobrien	    make_expr_symbol (&expr), line_delta, NULL);
76277298Sobrien}
76360484Sobrien
76477298Sobrien/* The function estimates the size of a rs_dwarf2dbg variant frag
76577298Sobrien   based on the current values of the symbols.  It is called before
76677298Sobrien   the relaxation loop.  We set fr_subtype to the expected length.  */
76760484Sobrien
76877298Sobrienint
76977298Sobriendwarf2dbg_estimate_size_before_relax (frag)
77077298Sobrien     fragS *frag;
77177298Sobrien{
77277298Sobrien  offsetT addr_delta;
77377298Sobrien  int size;
77460484Sobrien
77577298Sobrien  addr_delta = resolve_symbol_value (frag->fr_symbol, 0);
77677298Sobrien  size = size_inc_line_addr (frag->fr_offset, addr_delta);
77760484Sobrien
77877298Sobrien  frag->fr_subtype = size;
77960484Sobrien
78077298Sobrien  return size;
78160484Sobrien}
78260484Sobrien
78377298Sobrien/* This function relaxes a rs_dwarf2dbg variant frag based on the
78477298Sobrien   current values of the symbols.  fr_subtype is the current length
78577298Sobrien   of the frag.  This returns the change in frag length.  */
78677298Sobrien
78777298Sobrienint
78877298Sobriendwarf2dbg_relax_frag (frag)
78977298Sobrien     fragS *frag;
79077298Sobrien{
79177298Sobrien  int old_size, new_size;
79277298Sobrien
79377298Sobrien  old_size = frag->fr_subtype;
79477298Sobrien  new_size = dwarf2dbg_estimate_size_before_relax (frag);
79577298Sobrien
79677298Sobrien  return new_size - old_size;
79777298Sobrien}
79877298Sobrien
79977298Sobrien/* This function converts a rs_dwarf2dbg variant frag into a normal
80077298Sobrien   fill frag.  This is called after all relaxation has been done.
80177298Sobrien   fr_subtype will be the desired length of the frag.  */
80277298Sobrien
80377298Sobrienvoid
80477298Sobriendwarf2dbg_convert_frag (frag)
80577298Sobrien     fragS *frag;
80677298Sobrien{
80777298Sobrien  offsetT addr_diff;
80877298Sobrien
80977298Sobrien  addr_diff = resolve_symbol_value (frag->fr_symbol, 1);
81077298Sobrien
81177298Sobrien  /* fr_var carries the max_chars that we created the fragment with.
81277298Sobrien     fr_subtype carries the current expected length.  We must, of
81377298Sobrien     course, have allocated enough memory earlier.  */
81477298Sobrien  assert (frag->fr_var >= (int) frag->fr_subtype);
81577298Sobrien
81677298Sobrien  emit_inc_line_addr (frag->fr_offset, addr_diff,
81777298Sobrien		      frag->fr_literal + frag->fr_fix, frag->fr_subtype);
81877298Sobrien
81977298Sobrien  frag->fr_fix += frag->fr_subtype;
82077298Sobrien  frag->fr_type = rs_fill;
82177298Sobrien  frag->fr_var = 0;
82277298Sobrien  frag->fr_offset = 0;
82377298Sobrien}
82477298Sobrien
82577298Sobrien/* Generate .debug_line content for the chain of line number entries
82677298Sobrien   beginning at E, for segment SEG.  */
82777298Sobrien
82860484Sobrienstatic void
82977298Sobrienprocess_entries (seg, e)
83077298Sobrien     segT seg;
83177298Sobrien     struct line_entry *e;
83260484Sobrien{
83377298Sobrien  unsigned filenum = 1;
83477298Sobrien  unsigned line = 1;
83577298Sobrien  unsigned column = 0;
83677298Sobrien  unsigned flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_BEGIN_STMT : 0;
83777298Sobrien  fragS *frag = NULL;
83877298Sobrien  fragS *last_frag;
83977298Sobrien  addressT frag_ofs = 0;
84077298Sobrien  addressT last_frag_ofs;
84177298Sobrien  struct line_entry *next;
84260484Sobrien
84377298Sobrien  while (e)
84477298Sobrien    {
84577298Sobrien      int changed = 0;
84660484Sobrien
84777298Sobrien      if (filenum != e->loc.filenum)
84860484Sobrien	{
84977298Sobrien	  filenum = e->loc.filenum;
85077298Sobrien	  out_opcode (DW_LNS_set_file);
85177298Sobrien	  out_uleb128 (filenum);
85277298Sobrien	  changed = 1;
85377298Sobrien	}
85477298Sobrien
85577298Sobrien      if (column != e->loc.column)
85677298Sobrien	{
85777298Sobrien	  column = e->loc.column;
85877298Sobrien	  out_opcode (DW_LNS_set_column);
85977298Sobrien	  out_uleb128 (column);
86077298Sobrien	  changed = 1;
86177298Sobrien	}
86277298Sobrien
86377298Sobrien      if ((e->loc.flags ^ flags) & DWARF2_FLAG_BEGIN_STMT)
86477298Sobrien	{
86577298Sobrien	  flags = e->loc.flags;
86677298Sobrien	  out_opcode (DW_LNS_negate_stmt);
86777298Sobrien	  changed = 1;
86877298Sobrien	}
86977298Sobrien
87077298Sobrien      if (e->loc.flags & DWARF2_FLAG_BEGIN_BLOCK)
87177298Sobrien	{
87277298Sobrien	  out_opcode (DW_LNS_set_basic_block);
87377298Sobrien	  changed = 1;
87477298Sobrien	}
87577298Sobrien
87677298Sobrien      if (line != e->loc.line || changed)
87777298Sobrien	{
87877298Sobrien	  int line_delta = e->loc.line - line;
87977298Sobrien	  if (frag == NULL)
88060484Sobrien	    {
88177298Sobrien	      out_set_addr (seg, e->frag, e->frag_ofs);
88277298Sobrien	      out_inc_line_addr (line_delta, 0);
88360484Sobrien	    }
88477298Sobrien	  else if (frag == e->frag)
88577298Sobrien	    out_inc_line_addr (line_delta, e->frag_ofs - frag_ofs);
88677298Sobrien	  else
88777298Sobrien	    relax_inc_line_addr (line_delta, seg, e->frag, e->frag_ofs,
88877298Sobrien				 frag, frag_ofs);
88977298Sobrien
89077298Sobrien	  frag = e->frag;
89177298Sobrien	  frag_ofs = e->frag_ofs;
89277298Sobrien	  line = e->loc.line;
89360484Sobrien	}
89477298Sobrien      else if (frag == NULL)
89577298Sobrien	{
89677298Sobrien	  out_set_addr (seg, e->frag, e->frag_ofs);
89777298Sobrien	  frag = e->frag;
89877298Sobrien	  frag_ofs = e->frag_ofs;
89977298Sobrien	}
90077298Sobrien
90177298Sobrien      next = e->next;
90277298Sobrien      free (e);
90377298Sobrien      e = next;
90460484Sobrien    }
90577298Sobrien
90677298Sobrien  /* Emit a DW_LNE_end_sequence for the end of the section.  */
90777298Sobrien  last_frag = last_frag_for_seg (seg);
90877298Sobrien  last_frag_ofs = get_frag_fix (last_frag);
90977298Sobrien  if (frag == last_frag)
91077298Sobrien    out_inc_line_addr (INT_MAX, last_frag_ofs - frag_ofs);
91177298Sobrien  else
91277298Sobrien    relax_inc_line_addr (INT_MAX, seg, last_frag, last_frag_ofs,
91377298Sobrien			 frag, frag_ofs);
91460484Sobrien}
91560484Sobrien
91677298Sobrien/* Emit the directory and file tables for .debug_line.  */
91777298Sobrien
91860484Sobrienstatic void
91977298Sobrienout_file_list ()
92060484Sobrien{
92160484Sobrien  size_t size;
92260484Sobrien  char *cp;
92377298Sobrien  unsigned int i;
92460484Sobrien
92577298Sobrien  /* Terminate directory list.  */
92677298Sobrien  out_byte ('\0');
92777298Sobrien
92877298Sobrien  for (i = 1; i < files_in_use; ++i)
92960484Sobrien    {
93077298Sobrien      if (files[i].filename == NULL)
93177298Sobrien	{
93277298Sobrien	  as_bad (_("Unassigned file number %u"), i);
93377298Sobrien	  continue;
93477298Sobrien	}
93577298Sobrien
93677298Sobrien      size = strlen (files[i].filename) + 1;
93760484Sobrien      cp = frag_more (size);
93877298Sobrien      memcpy (cp, files[i].filename, size);
93960484Sobrien
94077298Sobrien      out_uleb128 (files[i].dir);	/* directory number */
94160484Sobrien      out_uleb128 (0);			/* last modification timestamp */
94260484Sobrien      out_uleb128 (0);			/* filesize */
94360484Sobrien    }
94477298Sobrien
94577298Sobrien  /* Terminate filename list.  */
94677298Sobrien  out_byte (0);
94760484Sobrien}
94860484Sobrien
94977298Sobrien/* Emit the collected .debug_line data.  */
95077298Sobrien
95160484Sobrienstatic void
95277298Sobrienout_debug_line (line_seg)
95377298Sobrien     segT line_seg;
95460484Sobrien{
95577298Sobrien  expressionS expr;
95677298Sobrien  symbolS *line_start;
95777298Sobrien  symbolS *prologue_end;
95877298Sobrien  symbolS *line_end;
95977298Sobrien  struct line_seg *s;
96077298Sobrien
96177298Sobrien  subseg_set (line_seg, 0);
96277298Sobrien
96377298Sobrien  line_start = symbol_new_now ();
96477298Sobrien  prologue_end = symbol_make (fake_label_name);
96577298Sobrien  line_end = symbol_make (fake_label_name);
96677298Sobrien
96777298Sobrien  /* Total length of the information for this compilation unit.  */
96877298Sobrien  expr.X_op = O_subtract;
96977298Sobrien  expr.X_add_symbol = line_end;
97077298Sobrien  expr.X_op_symbol = line_start;
97177298Sobrien  expr.X_add_number = -4;
97277298Sobrien  emit_expr (&expr, 4);
97377298Sobrien
97477298Sobrien  /* Version.  */
97577298Sobrien  out_two (2);
97677298Sobrien
97777298Sobrien  /* Length of the prologue following this length.  */
97877298Sobrien  expr.X_op = O_subtract;
97977298Sobrien  expr.X_add_symbol = prologue_end;
98077298Sobrien  expr.X_op_symbol = line_start;
98177298Sobrien  expr.X_add_number = - (4 + 2 + 4);
98277298Sobrien  emit_expr (&expr, 4);
98377298Sobrien
98477298Sobrien  /* Parameters of the state machine.  */
98577298Sobrien  out_byte (DWARF2_LINE_MIN_INSN_LENGTH);
98677298Sobrien  out_byte (DWARF2_LINE_DEFAULT_IS_STMT);
98777298Sobrien  out_byte (DWARF2_LINE_BASE);
98877298Sobrien  out_byte (DWARF2_LINE_RANGE);
98977298Sobrien  out_byte (DWARF2_LINE_OPCODE_BASE);
99077298Sobrien
99177298Sobrien  /* Standard opcode lengths.  */
99277298Sobrien  out_byte (0);			/* DW_LNS_copy */
99377298Sobrien  out_byte (1);			/* DW_LNS_advance_pc */
99477298Sobrien  out_byte (1);			/* DW_LNS_advance_line */
99577298Sobrien  out_byte (1);			/* DW_LNS_set_file */
99677298Sobrien  out_byte (1);			/* DW_LNS_set_column */
99777298Sobrien  out_byte (0);			/* DW_LNS_negate_stmt */
99877298Sobrien  out_byte (0);			/* DW_LNS_set_basic_block */
99977298Sobrien  out_byte (0);			/* DW_LNS_const_add_pc */
100077298Sobrien  out_byte (1);			/* DW_LNS_fixed_advance_pc */
100177298Sobrien
100277298Sobrien  out_file_list ();
100377298Sobrien
100477298Sobrien  set_symbol_value_now (prologue_end);
100577298Sobrien
100677298Sobrien  /* For each section, emit a statement program.  */
100777298Sobrien  for (s = all_segs; s; s = s->next)
100877298Sobrien    process_entries (s->seg, s->head->head);
100977298Sobrien
101077298Sobrien  set_symbol_value_now (line_end);
101177298Sobrien}
101277298Sobrien
101377298Sobrien/* Emit data for .debug_aranges.  */
101477298Sobrien
101577298Sobrienstatic void
101677298Sobrienout_debug_aranges (aranges_seg, info_seg)
101777298Sobrien     segT aranges_seg;
101877298Sobrien     segT info_seg;
101977298Sobrien{
102077298Sobrien  unsigned int addr_size = sizeof_address;
102177298Sobrien  addressT size, skip;
102277298Sobrien  struct line_seg *s;
102377298Sobrien  expressionS expr;
102477298Sobrien  char *p;
102577298Sobrien
102677298Sobrien  size = 4 + 2 + 4 + 1 + 1;
102777298Sobrien
102877298Sobrien  skip = 2 * addr_size - (size & (2 * addr_size - 1));
102977298Sobrien  if (skip == 2 * addr_size)
103077298Sobrien    skip = 0;
103177298Sobrien  size += skip;
103277298Sobrien
103377298Sobrien  for (s = all_segs; s; s = s->next)
103477298Sobrien    size += 2 * addr_size;
103577298Sobrien
103677298Sobrien  size += 2 * addr_size;
103777298Sobrien
103877298Sobrien  subseg_set (aranges_seg, 0);
103977298Sobrien
104077298Sobrien  /* Length of the compilation unit.  */
104177298Sobrien  out_four (size - 4);
104277298Sobrien
104377298Sobrien  /* Version.  */
104477298Sobrien  out_two (2);
104577298Sobrien
104677298Sobrien  /* Offset to .debug_info.  */
104777298Sobrien  expr.X_op = O_symbol;
104877298Sobrien  expr.X_add_symbol = section_symbol (info_seg);
104977298Sobrien  expr.X_add_number = 0;
105077298Sobrien  emit_expr (&expr, 4);
105177298Sobrien
105277298Sobrien  /* Size of an address (offset portion).  */
105377298Sobrien  out_byte (addr_size);
105477298Sobrien
105577298Sobrien  /* Size of a segment descriptor.  */
105677298Sobrien  out_byte (0);
105777298Sobrien
105877298Sobrien  /* Align the header.  */
105977298Sobrien  if (skip)
106077298Sobrien    frag_align (ffs (2 * addr_size) - 1, 0, 0);
106177298Sobrien
106277298Sobrien  for (s = all_segs; s; s = s->next)
106360484Sobrien    {
106477298Sobrien      fragS *frag;
106577298Sobrien      symbolS *beg, *end;
106660484Sobrien
106777298Sobrien      frag = first_frag_for_seg (s->seg);
106877298Sobrien      beg = symbol_new (fake_label_name, s->seg, 0, frag);
106977298Sobrien      s->text_start = beg;
107060484Sobrien
107177298Sobrien      frag = last_frag_for_seg (s->seg);
107277298Sobrien      end = symbol_new (fake_label_name, s->seg, get_frag_fix (frag), frag);
107377298Sobrien      s->text_end = end;
107460484Sobrien
107577298Sobrien      expr.X_op = O_symbol;
107677298Sobrien      expr.X_add_symbol = beg;
107777298Sobrien      expr.X_add_number = 0;
107877298Sobrien      emit_expr (&expr, addr_size);
107977298Sobrien
108077298Sobrien      expr.X_op = O_subtract;
108177298Sobrien      expr.X_add_symbol = end;
108277298Sobrien      expr.X_op_symbol = beg;
108377298Sobrien      expr.X_add_number = 0;
108477298Sobrien      emit_expr (&expr, addr_size);
108560484Sobrien    }
108660484Sobrien
108777298Sobrien  p = frag_more (2 * addr_size);
108877298Sobrien  md_number_to_chars (p, 0, addr_size);
108977298Sobrien  md_number_to_chars (p + addr_size, 0, addr_size);
109077298Sobrien}
109160484Sobrien
109277298Sobrien/* Emit data for .debug_abbrev.  Note that this must be kept in
109377298Sobrien   sync with out_debug_info below.  */
109460484Sobrien
109577298Sobrienstatic void
109677298Sobrienout_debug_abbrev (abbrev_seg)
109777298Sobrien     segT abbrev_seg;
109877298Sobrien{
109977298Sobrien  subseg_set (abbrev_seg, 0);
110077298Sobrien
110177298Sobrien  out_uleb128 (1);
110277298Sobrien  out_uleb128 (DW_TAG_compile_unit);
110377298Sobrien  out_byte (DW_CHILDREN_no);
110477298Sobrien  out_abbrev (DW_AT_stmt_list, DW_FORM_data4);
110577298Sobrien  if (all_segs->next == NULL)
110660484Sobrien    {
110777298Sobrien      out_abbrev (DW_AT_low_pc, DW_FORM_addr);
110877298Sobrien      out_abbrev (DW_AT_high_pc, DW_FORM_addr);
110960484Sobrien    }
111077298Sobrien  out_abbrev (DW_AT_comp_dir, DW_FORM_string);
111177298Sobrien  out_abbrev (DW_AT_producer, DW_FORM_string);
111277298Sobrien  out_abbrev (DW_AT_language, DW_FORM_data2);
111377298Sobrien  out_abbrev (0, 0);
111477298Sobrien
111577298Sobrien  /* Terminate the abbreviations for this compilation unit.  */
111677298Sobrien  out_byte (0);
111760484Sobrien}
111860484Sobrien
111977298Sobrien/* Emit a description of this compilation unit for .debug_info.  */
112077298Sobrien
112177298Sobrienstatic void
112277298Sobrienout_debug_info (info_seg, abbrev_seg, line_seg)
112377298Sobrien     segT info_seg;
112477298Sobrien     segT abbrev_seg;
112577298Sobrien     segT line_seg;
112660484Sobrien{
112777298Sobrien  char producer[128];
112877298Sobrien  char *comp_dir;
112977298Sobrien  expressionS expr;
113077298Sobrien  symbolS *info_start;
113177298Sobrien  symbolS *info_end;
113277298Sobrien  char *p;
113377298Sobrien  int len;
113460484Sobrien
113577298Sobrien  subseg_set (info_seg, 0);
113660484Sobrien
113777298Sobrien  info_start = symbol_new_now ();
113877298Sobrien  info_end = symbol_make (fake_label_name);
113960484Sobrien
114077298Sobrien  /* Compilation Unit length.  */
114177298Sobrien  expr.X_op = O_subtract;
114277298Sobrien  expr.X_add_symbol = info_end;
114377298Sobrien  expr.X_op_symbol = info_start;
114477298Sobrien  expr.X_add_number = -4;
114577298Sobrien  emit_expr (&expr, 4);
114660484Sobrien
114777298Sobrien  /* DWARF version.  */
114877298Sobrien  out_two (2);
114960484Sobrien
115077298Sobrien  /* .debug_abbrev offset */
115177298Sobrien  expr.X_op = O_symbol;
115277298Sobrien  expr.X_add_symbol = section_symbol (abbrev_seg);
115377298Sobrien  expr.X_add_number = 0;
115477298Sobrien  emit_expr (&expr, 4);
115560484Sobrien
115677298Sobrien  /* Target address size.  */
115777298Sobrien  out_byte (sizeof_address);
115860484Sobrien
115977298Sobrien  /* DW_TAG_compile_unit DIE abbrev */
116077298Sobrien  out_uleb128 (1);
116160484Sobrien
116277298Sobrien  /* DW_AT_stmt_list */
116377298Sobrien  expr.X_op = O_symbol;
116477298Sobrien  expr.X_add_symbol = section_symbol (line_seg);
116577298Sobrien  expr.X_add_number = 0;
116677298Sobrien  emit_expr (&expr, 4);
116760484Sobrien
116877298Sobrien  /* These two attributes may only be emitted if all of the code is
116977298Sobrien     contiguous.  Multiple sections are not that.  */
117077298Sobrien  if (all_segs->next == NULL)
117177298Sobrien    {
117277298Sobrien      /* DW_AT_low_pc */
117377298Sobrien      expr.X_op = O_symbol;
117477298Sobrien      expr.X_add_symbol = all_segs->text_start;
117577298Sobrien      expr.X_add_number = 0;
117677298Sobrien      emit_expr (&expr, sizeof_address);
117760484Sobrien
117877298Sobrien      /* DW_AT_high_pc */
117977298Sobrien      expr.X_op = O_symbol;
118077298Sobrien      expr.X_add_symbol = all_segs->text_end;
118177298Sobrien      expr.X_add_number = 0;
118277298Sobrien      emit_expr (&expr, sizeof_address);
118377298Sobrien    }
118460484Sobrien
118577298Sobrien  /* DW_AT_comp_dir */
118677298Sobrien  comp_dir = getpwd ();
118777298Sobrien  len = strlen (comp_dir) + 1;
118877298Sobrien  p = frag_more (len);
118977298Sobrien  memcpy (p, comp_dir, len);
119077298Sobrien
119177298Sobrien  /* DW_AT_producer */
119277298Sobrien  sprintf (producer, "GNU AS %s", VERSION);
119377298Sobrien  len = strlen (producer) + 1;
119477298Sobrien  p = frag_more (len);
119577298Sobrien  memcpy (p, producer, len);
119677298Sobrien
119777298Sobrien  /* DW_AT_language.  Yes, this is probably not really MIPS, but the
119877298Sobrien     dwarf2 draft has no standard code for assembler.  */
119977298Sobrien  out_two (DW_LANG_Mips_Assembler);
120077298Sobrien
120177298Sobrien  set_symbol_value_now (info_end);
120260484Sobrien}
120360484Sobrien
120460484Sobrienvoid
120577298Sobriendwarf2_finish ()
120660484Sobrien{
120777298Sobrien  segT line_seg;
120877298Sobrien  struct line_seg *s;
120960484Sobrien
121077298Sobrien  /* If no debug information was recorded, nothing to do.  */
121177298Sobrien  if (all_segs == NULL)
121277298Sobrien    return;
121377298Sobrien
121477298Sobrien  /* Calculate the size of an address for the target machine.  */
121577298Sobrien  sizeof_address = bfd_arch_bits_per_address (stdoutput) / 8;
121677298Sobrien
121777298Sobrien  /* Create and switch to the line number section.  */
121877298Sobrien  line_seg = subseg_new (".debug_line", 0);
121977298Sobrien  bfd_set_section_flags (stdoutput, line_seg, SEC_READONLY);
122077298Sobrien
122177298Sobrien  /* For each subsection, chain the debug entries together.  */
122277298Sobrien  for (s = all_segs; s; s = s->next)
122360484Sobrien    {
122477298Sobrien      struct line_subseg *ss = s->head;
122577298Sobrien      struct line_entry **ptail = ss->ptail;
122677298Sobrien
122777298Sobrien      while ((ss = ss->next) != NULL)
122877298Sobrien	{
122977298Sobrien	  *ptail = ss->head;
123077298Sobrien	  ptail = ss->ptail;
123177298Sobrien	}
123260484Sobrien    }
123360484Sobrien
123477298Sobrien  out_debug_line (line_seg);
123560484Sobrien
123677298Sobrien  /* If this is assembler generated line info, we need .debug_info
123777298Sobrien     and .debug_abbrev sections as well.  */
123877298Sobrien  if (debug_type == DEBUG_DWARF2)
123977298Sobrien    {
124077298Sobrien      segT abbrev_seg;
124177298Sobrien      segT info_seg;
124277298Sobrien      segT aranges_seg;
124360484Sobrien
124477298Sobrien      info_seg = subseg_new (".debug_info", 0);
124577298Sobrien      abbrev_seg = subseg_new (".debug_abbrev", 0);
124677298Sobrien      aranges_seg = subseg_new (".debug_aranges", 0);
124760484Sobrien
124877298Sobrien      bfd_set_section_flags (stdoutput, info_seg, SEC_READONLY);
124977298Sobrien      bfd_set_section_flags (stdoutput, abbrev_seg, SEC_READONLY);
125077298Sobrien      bfd_set_section_flags (stdoutput, aranges_seg, SEC_READONLY);
125177298Sobrien
125277298Sobrien      record_alignment (aranges_seg, ffs (2 * sizeof_address) - 1);
125377298Sobrien
125477298Sobrien      out_debug_aranges (aranges_seg, info_seg);
125577298Sobrien      out_debug_abbrev (abbrev_seg);
125677298Sobrien      out_debug_info (info_seg, abbrev_seg, line_seg);
125777298Sobrien    }
125860484Sobrien}
125960484Sobrien
126077298Sobrien#else
126160484Sobrienvoid
126277298Sobriendwarf2_finish ()
126360484Sobrien{
126477298Sobrien}
126560484Sobrien
126677298Sobrienint
126777298Sobriendwarf2dbg_estimate_size_before_relax (frag)
126877298Sobrien     fragS *frag ATTRIBUTE_UNUSED;
126977298Sobrien{
127077298Sobrien  as_fatal (_("dwarf2 is not supported for this object file format"));
127177298Sobrien  return 0;
127277298Sobrien}
127360484Sobrien
127477298Sobrienint
127577298Sobriendwarf2dbg_relax_frag (frag)
127677298Sobrien     fragS *frag ATTRIBUTE_UNUSED;
127777298Sobrien{
127877298Sobrien  as_fatal (_("dwarf2 is not supported for this object file format"));
127977298Sobrien  return 0;
128077298Sobrien}
128160484Sobrien
128277298Sobrienvoid
128377298Sobriendwarf2dbg_convert_frag (frag)
128477298Sobrien     fragS *frag ATTRIBUTE_UNUSED;
128577298Sobrien{
128677298Sobrien  as_fatal (_("dwarf2 is not supported for this object file format"));
128760484Sobrien}
128860484Sobrien
128960484Sobrienvoid
129077298Sobriendwarf2_emit_insn (size)
129177298Sobrien     int size ATTRIBUTE_UNUSED;
129260484Sobrien{
129360484Sobrien}
129477298Sobrien
129577298Sobrienvoid
129677298Sobriendwarf2_directive_file (dummy)
129777298Sobrien     int dummy ATTRIBUTE_UNUSED;
129877298Sobrien{
129977298Sobrien  as_fatal (_("dwarf2 is not supported for this object file format"));
130077298Sobrien}
130177298Sobrien
130277298Sobrienvoid
130377298Sobriendwarf2_directive_loc (dummy)
130477298Sobrien     int dummy ATTRIBUTE_UNUSED;
130577298Sobrien{
130677298Sobrien  as_fatal (_("dwarf2 is not supported for this object file format"));
130777298Sobrien}
130877298Sobrien#endif /* BFD_ASSEMBLER */
1309