1/*
2
3  Copyright (C) 2000,2002,2004,2005,2006 Silicon Graphics, Inc.  All Rights Reserved.
4
5  This program is free software; you can redistribute it and/or modify it
6  under the terms of version 2.1 of the GNU Lesser General Public License
7  as published by the Free Software Foundation.
8
9  This program is distributed in the hope that it would be useful, but
10  WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13  Further, this software is distributed without any warranty that it is
14  free of the rightful claim of any third person regarding infringement
15  or the like.  Any license provided herein, whether implied or
16  otherwise, applies only to this software file.  Patent licenses, if
17  any, provided herein do not apply to combinations of this program with
18  other software, or any other product whatsoever.
19
20  You should have received a copy of the GNU Lesser General Public
21  License along with this program; if not, write the Free Software
22  Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
23  USA.
24
25  Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
26  Mountain View, CA 94043, or:
27
28  http://www.sgi.com
29
30  For further information regarding this notice, see:
31
32  http://oss.sgi.com/projects/GenInfo/NoticeExplan
33
34*/
35
36
37
38#include "config.h"
39#include "dwarf_incl.h"
40#include <stdio.h>
41#include <time.h>
42#include "dwarf_line.h"
43#ifdef HAVE_ALLOCA_H
44#include <alloca.h>
45#endif
46
47/* FIXME Need to add prologue_end epilogue_begin isa fields. */
48static void
49print_line_header(void)
50{
51    printf
52	("                                                         s b e\n"
53	 "                                                         t l s\n"
54	 "                                                         m c e\n"
55	 " section    op                                       col t k q\n"
56	 " offset     code               address     file line umn ? ? ?\n");
57}
58
59/* FIXME: print new line values:   prologue_end epilogue_begin isa */
60static void
61print_line_detail(char *prefix,
62		  int opcode,
63		  unsigned long long address,
64		  unsigned long file,
65		  unsigned long line,
66		  unsigned long column,
67		  int is_stmt, int basic_block, int end_sequence,
68		  int prologue_end, int epilogue_begin, int isa)
69{
70    printf("%-15s %2d 0x%08llx "
71	   "%2lu   %4lu %2lu   %1d %1d %1d\n",
72	   prefix,
73	   (int) opcode,
74	   (long long) address,
75	   (unsigned long) file,
76	   (unsigned long) line,
77	   (unsigned long) column,
78	   (int) is_stmt, (int) basic_block, (int) end_sequence);
79
80}
81
82
83/*
84	return DW_DLV_OK if ok. else DW_DLV_NO_ENTRY or DW_DLV_ERROR
85*/
86int
87_dwarf_internal_printlines(Dwarf_Die die, Dwarf_Error * error)
88{
89    /*
90       This pointer is used to scan the portion of the .debug_line
91       section for the current cu. */
92    Dwarf_Small *line_ptr;
93    Dwarf_Small *orig_line_ptr;
94
95    /*
96       This points to the last byte of the .debug_line portion for the
97       current cu. */
98    Dwarf_Small *line_ptr_end = 0;
99
100    /*
101       Pointer to a DW_AT_stmt_list attribute in case it exists in the
102       die. */
103    Dwarf_Attribute stmt_list_attr;
104
105    /* Pointer to DW_AT_comp_dir attribute in die. */
106    Dwarf_Attribute comp_dir_attr;
107
108    /* Pointer to name of compilation directory. */
109    Dwarf_Small *comp_dir = NULL;
110
111    /*
112       Offset into .debug_line specified by a DW_AT_stmt_list
113       attribute. */
114    Dwarf_Unsigned line_offset;
115
116    struct Line_Table_Prefix_s prefix;
117
118
119    /* These are the state machine state variables. */
120    Dwarf_Addr address = 0;
121    Dwarf_Word file = 1;
122    Dwarf_Word line = 1;
123    Dwarf_Word column = 0;
124    Dwarf_Bool is_stmt = false;
125    Dwarf_Bool basic_block = false;
126    Dwarf_Bool end_sequence = false;
127    Dwarf_Bool prologue_end = false;
128    Dwarf_Bool epilogue_begin = false;
129    Dwarf_Small isa = 0;
130
131
132    Dwarf_Sword i;
133
134    /*
135       This is the current opcode read from the statement program. */
136    Dwarf_Small opcode;
137
138
139    /*
140       These variables are used to decode leb128 numbers. Leb128_num
141       holds the decoded number, and leb128_length is its length in
142       bytes. */
143    Dwarf_Word leb128_num;
144    Dwarf_Word leb128_length;
145    Dwarf_Sword advance_line;
146    Dwarf_Half attrform = 0;
147
148
149    /*
150       This is the operand of the latest fixed_advance_pc extended
151       opcode. */
152    Dwarf_Half fixed_advance_pc;
153
154
155     /*REFERENCED*/		/* Not used in this instance of the
156				   macro */
157    int local_extension_size;
158
159    /* The Dwarf_Debug this die belongs to. */
160    Dwarf_Debug dbg;
161    int resattr;
162    int lres;
163
164    int res;
165
166    /* ***** BEGIN CODE ***** */
167
168    if (error != NULL)
169	*error = NULL;
170
171    CHECK_DIE(die, DW_DLV_ERROR)
172	dbg = die->di_cu_context->cc_dbg;
173
174    res =
175	_dwarf_load_section(dbg,
176			    dbg->de_debug_line_index,
177			    &dbg->de_debug_line, error);
178    if (res != DW_DLV_OK) {
179	return res;
180    }
181
182    resattr = dwarf_attr(die, DW_AT_stmt_list, &stmt_list_attr, error);
183    if (resattr != DW_DLV_OK) {
184	return resattr;
185    }
186
187
188
189  /* The list of relevant FORMs is small.
190   DW_FORM_data4, DW_FORM_data8, DW_FORM_sec_offset
191   */
192  lres = dwarf_whatform(stmt_list_attr,&attrform,error);
193  if (lres != DW_DLV_OK) {
194    return lres;
195  }
196  if (attrform != DW_FORM_data4 && attrform != DW_FORM_data8 &&
197      attrform != DW_FORM_sec_offset ) {
198    _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
199    return (DW_DLV_ERROR);
200  }
201  lres = dwarf_global_formref(stmt_list_attr, &line_offset, error);
202  if (lres != DW_DLV_OK) {
203    return lres;
204  }
205
206    if (line_offset >= dbg->de_debug_line_size) {
207	_dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
208	return (DW_DLV_ERROR);
209    }
210    orig_line_ptr = dbg->de_debug_line;
211    line_ptr = dbg->de_debug_line + line_offset;
212    dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR);
213
214    /*
215       If die has DW_AT_comp_dir attribute, get the string that names
216       the compilation directory. */
217    resattr = dwarf_attr(die, DW_AT_comp_dir, &comp_dir_attr, error);
218    if (resattr == DW_DLV_ERROR) {
219	return resattr;
220    }
221    if (resattr == DW_DLV_OK) {
222	int cres;
223	char *cdir;
224
225	cres = dwarf_formstring(comp_dir_attr, &cdir, error);
226	if (cres == DW_DLV_ERROR) {
227	    return cres;
228	} else if (cres == DW_DLV_OK) {
229	    comp_dir = (Dwarf_Small *) cdir;
230	}
231    }
232    if (resattr == DW_DLV_OK) {
233	dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR);
234    }
235
236    dwarf_init_line_table_prefix(&prefix);
237    {
238	Dwarf_Small *line_ptr_out = 0;
239	int dres = dwarf_read_line_table_prefix(dbg,
240						line_ptr,
241						dbg->
242						de_debug_line_size -
243						line_offset,
244						&line_ptr_out,
245						&prefix, error);
246
247	if (dres == DW_DLV_ERROR) {
248	    dwarf_free_line_table_prefix(&prefix);
249	    return dres;
250	}
251	if (dres == DW_DLV_NO_ENTRY) {
252	    dwarf_free_line_table_prefix(&prefix);
253	    return dres;
254	}
255	line_ptr_end = prefix.pf_line_ptr_end;
256	line_ptr = line_ptr_out;
257    }
258
259
260
261    printf("total line info length %ld bytes, "
262	   "line offset 0x%llx %lld\n",
263	   (long) prefix.pf_total_length,
264	   (long long) line_offset, (long long) line_offset);
265    printf("compilation_directory %s\n",
266	   comp_dir ? ((char *) comp_dir) : "");
267
268    printf("  min instruction length %d\n",
269	   (int) prefix.pf_minimum_instruction_length);
270    printf("  default is stmt        %d\n", (int)
271	   prefix.pf_default_is_stmt);
272    printf("  line base              %d\n", (int)
273	   prefix.pf_line_base);
274    printf("  line_range             %d\n", (int)
275	   prefix.pf_line_range);
276
277
278    for (i = 1; i < prefix.pf_opcode_base; i++) {
279	printf("  opcode[%d] length %d\n", (int) i,
280	       (int) prefix.pf_opcode_length_table[i - 1]);
281    }
282
283    for (i = 0; i < prefix.pf_include_directories_count; ++i) {
284	printf("  include dir[%d] %s\n",
285	       (int) i, prefix.pf_include_directories[i]);
286    }
287
288
289    for (i = 0; i < prefix.pf_files_count; ++i) {
290	struct Line_Table_File_Entry_s *lfile =
291	    prefix.pf_line_table_file_entries + i;
292
293	Dwarf_Unsigned tlm2 = lfile->lte_last_modification_time;
294	Dwarf_Unsigned di = lfile->lte_directory_index;
295	Dwarf_Unsigned fl = lfile->lte_length_of_file;
296
297	printf("  file[%d]  %s\n",
298	       (int) i, (char *) lfile->lte_filename);
299
300	printf("    dir index %d\n", (int) di);
301	{
302	    time_t tt = (time_t) tlm2;
303
304	    printf("    last time 0x%x %s",	/* ctime supplies
305						   newline */
306		   (unsigned) tlm2, ctime(&tt));
307	}
308	printf("    file length %ld 0x%lx\n",
309	       (long) fl, (unsigned long) fl);
310
311
312    }
313
314
315    {
316	unsigned long long offset = line_ptr - orig_line_ptr;
317
318	printf("  statement prog offset in section: %llu 0x%llx\n",
319	       offset, offset);
320    }
321
322    /* Initialize the part of the state machine dependent on the
323       prefix.  */
324    is_stmt = prefix.pf_default_is_stmt;
325
326
327    print_line_header();
328    /* Start of statement program.  */
329    while (line_ptr < line_ptr_end) {
330	int type;
331
332	printf(" [0x%06llx] ", (long long) (line_ptr - orig_line_ptr));
333	opcode = *(Dwarf_Small *) line_ptr;
334	line_ptr++;
335	/* 'type' is the output */
336	WHAT_IS_OPCODE(type, opcode, prefix.pf_opcode_base,
337		       prefix.pf_opcode_length_table, line_ptr,
338		       prefix.pf_std_op_count);
339
340	if (type == LOP_DISCARD) {
341	    int oc;
342	    int opcnt = prefix.pf_opcode_length_table[opcode];
343
344	    printf(" DISCARD standard opcode %d with %d operands: "
345		   "not understood:", opcode, opcnt);
346	    for (oc = 0; oc < opcnt; oc++) {
347		/*
348		 * Read and discard operands we don't
349		 * understand.
350		 * Arbitrary choice of unsigned read.
351		 * Signed read would work as well.
352		 */
353		Dwarf_Unsigned utmp2;
354
355		DECODE_LEB128_UWORD(line_ptr, utmp2)
356		    printf(" %llu (0x%llx)",
357			   (unsigned long long) utmp2,
358			   (unsigned long long) utmp2);
359	    }
360
361	    printf("\n");
362	    /* do nothing, necessary ops done */
363	} else if (type == LOP_SPECIAL) {
364	    /* This op code is a special op in the object, no matter
365	       that it might fall into the standard op range in this
366	       compile Thatis, these are special opcodes between
367	       special_opcode_base and MAX_LINE_OP_CODE.  (including
368	       special_opcode_base and MAX_LINE_OP_CODE) */
369	    char special[50];
370	    unsigned origop = opcode;
371
372	    opcode = opcode - prefix.pf_opcode_base;
373	    address = address + prefix.pf_minimum_instruction_length *
374		(opcode / prefix.pf_line_range);
375	    line =
376		line + prefix.pf_line_base +
377		opcode % prefix.pf_line_range;
378
379	    sprintf(special, "Specialop %3u", origop);
380	    print_line_detail(special,
381			      opcode, address, (int) file, line, column,
382			      is_stmt, basic_block, end_sequence,
383			      prologue_end, epilogue_begin, isa);
384
385	    basic_block = false;
386
387	} else if (type == LOP_STANDARD) {
388	    switch (opcode) {
389
390	    case DW_LNS_copy:{
391
392		    print_line_detail("DW_LNS_copy",
393				      opcode, address, file, line,
394				      column, is_stmt, basic_block,
395				      end_sequence, prologue_end,
396				      epilogue_begin, isa);
397
398		    basic_block = false;
399		    break;
400		}
401
402	    case DW_LNS_advance_pc:{
403		    Dwarf_Unsigned utmp2;
404
405
406		    DECODE_LEB128_UWORD(line_ptr, utmp2)
407			printf("DW_LNS_advance_pc val %lld 0x%llx\n",
408			       (long long) (Dwarf_Word) utmp2,
409			       (long long) (Dwarf_Word) utmp2);
410		    leb128_num = (Dwarf_Word) utmp2;
411		    address =
412			address +
413			prefix.pf_minimum_instruction_length *
414			leb128_num;
415		    break;
416		}
417
418	    case DW_LNS_advance_line:{
419		    Dwarf_Signed stmp;
420
421
422		    DECODE_LEB128_SWORD(line_ptr, stmp)
423			advance_line = (Dwarf_Sword) stmp;
424		    printf("DW_LNS_advance_line val %lld 0x%llx\n",
425			   (long long) advance_line,
426			   (long long) advance_line);
427		    line = line + advance_line;
428		    break;
429		}
430
431	    case DW_LNS_set_file:{
432		    Dwarf_Unsigned utmp2;
433
434
435		    DECODE_LEB128_UWORD(line_ptr, utmp2)
436			file = (Dwarf_Word) utmp2;
437		    printf("DW_LNS_set_file  %ld\n", (long) file);
438		    break;
439		}
440
441	    case DW_LNS_set_column:{
442		    Dwarf_Unsigned utmp2;
443
444
445		    DECODE_LEB128_UWORD(line_ptr, utmp2)
446			column = (Dwarf_Word) utmp2;
447		    printf("DW_LNS_set_column val %lld 0x%llx\n",
448			   (long long) column, (long long) column);
449		    break;
450		}
451
452	    case DW_LNS_negate_stmt:{
453		    is_stmt = !is_stmt;
454		    printf("DW_LNS_negate_stmt\n");
455		    break;
456		}
457
458	    case DW_LNS_set_basic_block:{
459
460		    printf("DW_LNS_set_basic_block\n");
461		    basic_block = true;
462		    break;
463		}
464
465	    case DW_LNS_const_add_pc:{
466		    opcode = MAX_LINE_OP_CODE - prefix.pf_opcode_base;
467		    address =
468			address +
469			prefix.pf_minimum_instruction_length * (opcode /
470								prefix.
471								pf_line_range);
472
473		    printf("DW_LNS_const_add_pc new address 0x%llx\n",
474			   (long long) address);
475		    break;
476		}
477
478	    case DW_LNS_fixed_advance_pc:{
479
480		    READ_UNALIGNED(dbg, fixed_advance_pc, Dwarf_Half,
481				   line_ptr, sizeof(Dwarf_Half));
482		    line_ptr += sizeof(Dwarf_Half);
483		    address = address + fixed_advance_pc;
484		    printf("DW_LNS_fixed_advance_pc val %lld 0x%llx"
485			   " new address 0x%llx\n",
486			   (long long) fixed_advance_pc,
487			   (long long) fixed_advance_pc,
488			   (long long) address);
489		    break;
490		}
491	    case DW_LNS_set_prologue_end:{
492
493		    prologue_end = true;
494		    printf("DW_LNS_set_prologue_end set true.\n");
495		    break;
496
497
498		}
499		/* New in DWARF3 */
500	    case DW_LNS_set_epilogue_begin:{
501		    epilogue_begin = true;
502		    printf("DW_LNS_set_epilogue_begin set true.\n");
503		    break;
504		}
505
506		/* New in DWARF3 */
507	    case DW_LNS_set_isa:{
508		    Dwarf_Unsigned utmp2;
509
510		    DECODE_LEB128_UWORD(line_ptr, utmp2)
511			isa = utmp2;
512		    printf("DW_LNS_set_isa new value 0x%llx.\n",
513			   (unsigned long long) utmp2);
514		    if (isa != utmp2) {
515			/* The value of the isa did not fit in our
516			   local so we record it wrong. declare an
517			   error. */
518			dwarf_free_line_table_prefix(&prefix);
519
520			_dwarf_error(dbg, error,
521				     DW_DLE_LINE_NUM_OPERANDS_BAD);
522			return (DW_DLV_ERROR);
523		    }
524		    break;
525		}
526	    }
527
528
529	} else if (type == LOP_EXTENDED) {
530	    Dwarf_Unsigned utmp3 = 0;
531	    Dwarf_Word instr_length = 0;
532	    Dwarf_Small ext_opcode = 0;
533
534	    DECODE_LEB128_UWORD(line_ptr, utmp3)
535		instr_length = (Dwarf_Word) utmp3;
536	    ext_opcode = *(Dwarf_Small *) line_ptr;
537	    line_ptr++;
538	    switch (ext_opcode) {
539
540	    case DW_LNE_end_sequence:{
541		    end_sequence = true;
542
543		    print_line_detail("DW_LNE_end_sequence extended",
544				      opcode, address, file, line,
545				      column, is_stmt, basic_block,
546				      end_sequence, prologue_end,
547				      epilogue_begin, isa);
548
549		    address = 0;
550		    file = 1;
551		    line = 1;
552		    column = 0;
553		    is_stmt = prefix.pf_default_is_stmt;
554		    basic_block = false;
555		    end_sequence = false;
556		    prologue_end = false;
557		    epilogue_begin = false;
558
559
560		    break;
561		}
562
563	    case DW_LNE_set_address:{
564		    if (instr_length - 1 == dbg->de_pointer_size) {
565			READ_UNALIGNED(dbg, address, Dwarf_Addr,
566				       line_ptr, dbg->de_pointer_size);
567
568			line_ptr += dbg->de_pointer_size;
569			printf("DW_LNE_set_address address 0x%llx\n",
570			       (long long) address);
571		    } else {
572			dwarf_free_line_table_prefix(&prefix);
573			_dwarf_error(dbg, error,
574				     DW_DLE_LINE_SET_ADDR_ERROR);
575			return (DW_DLV_ERROR);
576		    }
577
578		    break;
579		}
580
581	    case DW_LNE_define_file:{
582
583
584		    Dwarf_Small *fn;
585		    Dwarf_Unsigned di;
586		    Dwarf_Unsigned tlm;
587		    Dwarf_Unsigned fl;
588
589		    fn = (Dwarf_Small *) line_ptr;
590		    line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
591
592		    di = _dwarf_decode_u_leb128(line_ptr,
593						&leb128_length);
594		    line_ptr = line_ptr + leb128_length;
595
596		    tlm = _dwarf_decode_u_leb128(line_ptr,
597						 &leb128_length);
598		    line_ptr = line_ptr + leb128_length;
599
600		    fl = _dwarf_decode_u_leb128(line_ptr,
601						&leb128_length);
602		    line_ptr = line_ptr + leb128_length;
603
604
605		    printf("DW_LNE_define_file %s \n", fn);
606		    printf("    dir index %d\n", (int) di);
607		    {
608			time_t tt3 = (time_t) tlm;
609
610			/* ctime supplies newline */
611			printf("    last time 0x%x %s",
612			       (unsigned) tlm, ctime(&tt3));
613		    }
614		    printf("    file length %ld 0x%lx\n",
615			   (long) fl, (unsigned long) fl);
616
617		    break;
618		}
619
620	    default:{
621		    dwarf_free_line_table_prefix(&prefix);
622		    _dwarf_error(dbg, error,
623				 DW_DLE_LINE_EXT_OPCODE_BAD);
624		    return (DW_DLV_ERROR);
625		}
626	    }
627
628	}
629    }
630
631    dwarf_free_line_table_prefix(&prefix);
632    return (DW_DLV_OK);
633}
634
635/*
636	Caller passes in compilation unit DIE.
637*/
638int
639_dwarf_print_lines(Dwarf_Die die, Dwarf_Error * error)
640{
641    int res;
642
643    res = _dwarf_internal_printlines(die, error);
644    if (res != DW_DLV_OK) {
645	return res;
646    }
647    return res;
648}
649