X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fdwarf2dbg.c;h=bd23b5a2a69c9e3ac70cb6d1073313b8fcfcebb8;hb=f0e652b4aa5420d23e7e7eef1146cb16daef13f3;hp=5e447abbb713255478aa2431ddd745833900cf60;hpb=dc9e099fc0eced486ae2b49455c9da113c11f4ff;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/dwarf2dbg.c b/gas/dwarf2dbg.c index 5e447abbb7..bd23b5a2a6 100644 --- a/gas/dwarf2dbg.c +++ b/gas/dwarf2dbg.c @@ -1,5 +1,5 @@ /* dwarf2dbg.c - DWARF2 debug support - Copyright (C) 1999 Free Software Foundation, Inc. + Copyright (C) 1999, 2000 Free Software Foundation, Inc. Contributed by David Mosberger-Tang This file is part of GAS, the GNU Assembler. @@ -78,7 +78,7 @@ is not made available by the GCC front-end. */ #define DWARF2_LINE_DEFAULT_IS_STMT 1 -/* Given a special op, return the line skip amount: */ +/* Given a special op, return the line skip amount. */ #define SPECIAL_LINE(op) \ (((op) - DWARF2_LINE_OPCODE_BASE)%DWARF2_LINE_RANGE + DWARF2_LINE_BASE) @@ -86,11 +86,11 @@ DWARF2_LINE_MIN_INSN_LENGTH. */ #define SPECIAL_ADDR(op) (((op) - DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE) -/* The maximum address skip amont that can be encoded with a special op: */ +/* The maximum address skip amount that can be encoded with a special op. */ #define MAX_SPECIAL_ADDR_DELTA SPECIAL_ADDR(255) #define INITIAL_STATE \ - /* initialize as per DWARF2.0 standard: */ \ + /* Initialize as per DWARF2.0 standard. */ \ 0, /* address */ \ 1, /* file */ \ 1, /* line */ \ @@ -118,6 +118,7 @@ static struct unsigned int any_dwarf2_directives : 1; /* did we emit any DWARF2 line debug directives? */ + fragS * frag; /* frag that "addr" is relative to */ segT text_seg; /* text segment "addr" is relative to */ subsegT text_subseg; segT line_seg; /* ".debug_line" segment */ @@ -131,9 +132,9 @@ static struct } *file; - struct dwarf2_line_info current; /* current source info: */ + struct dwarf2_line_info current; /* current source info */ - /* counters for statistical purposes: */ + /* counters for statistical purposes */ unsigned int num_line_entries; unsigned int opcode_hist[256]; /* histogram of opcode frequencies */ } @@ -149,6 +150,7 @@ ls = 0, 0, 0, + 0, NULL, { NULL, 0, 0, 0, 0 }, 0, @@ -172,8 +174,7 @@ ls = } }; - -/* Function prototypes: */ +/* Function prototypes. */ static void out_uleb128 PARAMS ((addressT)); static void out_sleb128 PARAMS ((offsetT)); static void gen_addr_line PARAMS ((int, addressT)); @@ -185,11 +186,11 @@ static void gen_dir_list PARAMS ((void)); static void gen_file_list PARAMS ((void)); static void print_stats PARAMS ((unsigned long)); - #define out_byte(byte) FRAG_APPEND_1_CHAR(byte) #define out_opcode(opc) (out_byte ((opc)), ++ls.opcode_hist[(opc) & 0xff]) /* Output an unsigned "little-endian base 128" number. */ + static void out_uleb128 (value) addressT value; @@ -208,6 +209,7 @@ out_uleb128 (value) } /* Output a signed "little-endian base 128" number. */ + static void out_sleb128 (value) offsetT value; @@ -229,6 +231,7 @@ out_sleb128 (value) /* Encode a pair of line and address skips as efficiently as possible. Note that the line skip is signed, whereas the address skip is unsigned. */ + static void gen_addr_line (line_delta, addr_delta) int line_delta; @@ -248,7 +251,7 @@ gen_addr_line (line_delta, addr_delta) tmp += DWARF2_LINE_OPCODE_BASE; - /* try using a special opcode: */ + /* Try using a special opcode. */ opcode = tmp + addr_delta*DWARF2_LINE_RANGE; if (opcode <= 255) { @@ -256,8 +259,8 @@ gen_addr_line (line_delta, addr_delta) return; } - /* try using DW_LNS_const_add_pc followed by special op: */ - opcode = tmp + (addr_delta - MAX_SPECIAL_ADDR_DELTA)*DWARF2_LINE_RANGE; + /* Try using DW_LNS_const_add_pc followed by special op. */ + opcode = tmp + (addr_delta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE; if (opcode <= 255) { out_opcode (DW_LNS_const_add_pc); @@ -269,9 +272,11 @@ gen_addr_line (line_delta, addr_delta) out_uleb128 (addr_delta); if (line_delta) - out_opcode (tmp); /* output line-delta */ + /* Output line-delta. */ + out_opcode (tmp); else - out_opcode (DW_LNS_copy); /* append new row with current info */ + /* Append new row with current info. */ + out_opcode (DW_LNS_copy); } static void @@ -282,7 +287,8 @@ reset_state_machine () ls.sm = initial_state; } -/* Set an absolute address (may results in a relocation entry): */ +/* Set an absolute address (may results in a relocation entry). */ + static void out_set_addr (addr) addressT addr; @@ -320,10 +326,12 @@ out_set_addr (addr) /* Emit DW_LNS_end_sequence and reset state machine. Does not preserve the current segment/sub-segment! */ + static void out_end_sequence () { addressT addr, delta; + fragS *text_frag; if (ls.text_seg) { @@ -333,17 +341,25 @@ out_end_sequence () #else addr = frag_now_fix (); #endif + text_frag = frag_now; subseg_set (ls.line_seg, DL_BODY); - if (addr < ls.sm.addr) + if (text_frag != ls.frag) { out_set_addr (addr); ls.sm.addr = addr; + ls.frag = text_frag; } else { - delta = addr - ls.sm.addr; + delta = (addr - ls.sm.addr) / DWARF2_LINE_MIN_INSN_LENGTH; if (delta > 0) - gen_addr_line (0, delta / DWARF2_LINE_MIN_INSN_LENGTH); + { + /* Advance address without updating the line-debug + matrix---the end_sequence entry is used only to tell + the debugger the end of the sequence. */ + out_opcode (DW_LNS_advance_pc); + out_uleb128 (delta); + } } } else @@ -359,7 +375,8 @@ out_end_sequence () /* Look up a filenumber either by filename or by filenumber. If both a filenumber and a filename are specified, lookup by filename takes precedence. If the filename cannot be found, it is added to the - filetable the filenumber for the new entry is returned. */ + filetable and the filenumber for the new entry is returned. */ + static int get_filenum (filenum, file) int filenum; @@ -368,15 +385,17 @@ get_filenum (filenum, file) int i, last = filenum - 1; char char0 = file[0]; - if (last >= ls.num_filenames) + /* If filenum is out of range of the filename table, then try using the + table entry returned from the previous call. */ + if (last >= ls.num_filenames || last < 0) last = ls.last_filename; - /* do a quick check against the previously used filename: */ + /* Do a quick check against the specified or previously used filenum. */ if (ls.num_filenames > 0 && ls.file[last].name[0] == char0 && strcmp (ls.file[last].name + 1, file + 1) == 0) return last + 1; - /* no match, fall back to simple linear scan: */ + /* No match, fall back to simple linear scan. */ for (i = 0; i < ls.num_filenames; ++i) { if (ls.file[i].name[0] == char0 @@ -387,7 +406,7 @@ get_filenum (filenum, file) } } - /* no match: enter new filename */ + /* No match, enter new filename. */ if (ls.num_filenames >= ls.filename_len) { ls.filename_len += 13; @@ -395,9 +414,13 @@ get_filenum (filenum, file) } ls.file[ls.num_filenames].dir = 0; ls.file[ls.num_filenames].name = file; + ls.last_filename = ls.num_filenames; return ++ls.num_filenames; } +/* Emit an entry in the line number table if the address or line has changed. + ADDR is relative to the current frag in the text section. */ + void dwarf2_gen_line_info (addr, l) addressT addr; @@ -407,6 +430,7 @@ dwarf2_gen_line_info (addr, l) unsigned int any_output = 0; subsegT saved_subseg; segT saved_seg; + fragS *saved_frag; if (flag_debug) fprintf (stderr, "line: addr %lx file `%s' line %u col %u flags %x\n", @@ -423,7 +447,14 @@ dwarf2_gen_line_info (addr, l) else if (l->filename) filenum = get_filenum (filenum, l->filename); else - return; /* no filename, no filnum => no play */ + /* No filename, no filnum => no play. */ + return; + + /* Must save these before the subseg_new call, as that call will change + them. */ + saved_seg = now_seg; + saved_subseg = now_subseg; + saved_frag = frag_now; if (!ls.line_seg) { @@ -439,21 +470,20 @@ dwarf2_gen_line_info (addr, l) /* We're going to need this symbol. */ secsym = symbol_find (".debug_line"); if (secsym != NULL) - symbol_set_bfdsym (secsym, ls.line_seg->symbol); + symbol_set_bfdsym (secsym, ls.line_seg->symbol); else - symbol_table_insert (section_symbol (ls.line_seg)); + symbol_table_insert (section_symbol (ls.line_seg)); #endif } - saved_seg = now_seg; - saved_subseg = now_subseg; subseg_set (ls.line_seg, DL_BODY); if (ls.text_seg != saved_seg || ls.text_subseg != saved_subseg) { if (!ls.sm.empty_sequence) { - out_end_sequence (); /* terminate previous sequence */ + /* Terminate previous sequence. */ + out_end_sequence (); ls.sm.empty_sequence = 1; } any_output = 1; @@ -461,6 +491,7 @@ dwarf2_gen_line_info (addr, l) ls.text_subseg = saved_subseg; out_set_addr (addr); ls.sm.addr = addr; + ls.frag = saved_frag; } if (ls.sm.filenum != filenum) @@ -494,18 +525,15 @@ dwarf2_gen_line_info (addr, l) if (ls.sm.line != l->line) { any_output = 1; - if (addr < ls.sm.addr) + if (saved_frag != ls.frag) { - /* This happens when a new frag got allocated (for whatever - reason). Deal with it by generating a reference symbol. - Note: no end_sequence needs to be generated because the - address did not really decrease (only the reference point - changed). - - ??? Perhaps we should directly check for a change of - frag_now instead? */ + /* If a new frag got allocated (for whatever reason), then + deal with it by generating a reference symbol. Note: no + end_sequence needs to be generated because the address did + not really decrease (only the reference point changed). */ out_set_addr (addr); ls.sm.addr = addr; + ls.frag = saved_frag; } gen_addr_line (l->line - ls.sm.line, (addr - ls.sm.addr) / DWARF2_LINE_MIN_INSN_LENGTH); @@ -548,7 +576,7 @@ gen_dir_list () } if (j >= num_dirs) { - /* didn't find this directory: append it to the list */ + /* Didn't find this directory: append it to the list. */ size_t size = strlen (str) + 1; cp = frag_more (size); memcpy (cp, str, size); @@ -558,7 +586,9 @@ gen_dir_list () ls.file[i].name = slash + 1; } } - out_byte ('\0'); /* terminate directory list */ + + /* Terminate directory list. */ + out_byte ('\0'); } static void @@ -578,7 +608,9 @@ gen_file_list () out_uleb128 (0); /* last modification timestamp */ out_uleb128 (0); /* filesize */ } - out_byte (0); /* terminate filename list */ + + /* Terminate filename list. */ + out_byte (0); } static void @@ -599,7 +631,7 @@ print_stats (total_size) fprintf (stderr, "\nStandard opcode histogram:\n"); - for (i = 0; i < sizeof (opc_name)/sizeof (opc_name[0]); ++i) + for (i = 0; i < sizeof (opc_name) / sizeof (opc_name[0]); ++i) { fprintf (stderr, "%s", opc_name[i]); for (j = strlen (opc_name[i]); j < 16; ++j) @@ -619,7 +651,8 @@ print_stats (total_size) j = SPECIAL_LINE (i); if (j == DWARF2_LINE_BASE) fprintf (stderr, "\n%4u: ", - DWARF2_LINE_MIN_INSN_LENGTH*SPECIAL_ADDR (i)); + ((unsigned int) + DWARF2_LINE_MIN_INSN_LENGTH * SPECIAL_ADDR (i))); fprintf (stderr, " %2u", ls.opcode_hist[i]); } fprintf (stderr, "\n"); @@ -634,7 +667,7 @@ dwarf2_finish () char *cp; if (!ls.line_seg) - /* no .debug_line segment, no work to do... */ + /* No .debug_line segment, no work to do. */ return; saved_seg = now_seg; @@ -644,13 +677,13 @@ dwarf2_finish () out_end_sequence (); total_size = body_size = frag_now_fix (); - /* now generate the directory and file lists: */ + /* Now generate the directory and file lists. */ subseg_set (ls.line_seg, DL_FILES); gen_dir_list (); gen_file_list (); total_size += frag_now_fix (); - /* and now the header ("statement program prolog", in DWARF2 lingo...) */ + /* And now the header ("statement program prolog", in DWARF2 lingo...). */ subseg_set (ls.line_seg, DL_PROLOG); cp = frag_more (15 + DWARF2_LINE_OPCODE_BASE - 1);