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
147    /*
148       This is the operand of the latest fixed_advance_pc extended
149       opcode. */
150    Dwarf_Half fixed_advance_pc;
151
152
153     /*REFERENCED*/		/* Not used in this instance of the
154				   macro */
155    int local_extension_size;
156
157    /* The Dwarf_Debug this die belongs to. */
158    Dwarf_Debug dbg;
159    int resattr;
160    int lres;
161
162    int res;
163
164    /* ***** BEGIN CODE ***** */
165
166    if (error != NULL)
167	*error = NULL;
168
169    CHECK_DIE(die, DW_DLV_ERROR)
170	dbg = die->di_cu_context->cc_dbg;
171
172    res =
173	_dwarf_load_section(dbg,
174			    dbg->de_debug_line_index,
175			    &dbg->de_debug_line, error);
176    if (res != DW_DLV_OK) {
177	return res;
178    }
179
180    resattr = dwarf_attr(die, DW_AT_stmt_list, &stmt_list_attr, error);
181    if (resattr != DW_DLV_OK) {
182	return resattr;
183    }
184
185
186
187    lres = dwarf_formudata(stmt_list_attr, &line_offset, error);
188    if (lres != DW_DLV_OK) {
189	return lres;
190    }
191
192    if (line_offset >= dbg->de_debug_line_size) {
193	_dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
194	return (DW_DLV_ERROR);
195    }
196    orig_line_ptr = dbg->de_debug_line;
197    line_ptr = dbg->de_debug_line + line_offset;
198    dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR);
199
200    /*
201       If die has DW_AT_comp_dir attribute, get the string that names
202       the compilation directory. */
203    resattr = dwarf_attr(die, DW_AT_comp_dir, &comp_dir_attr, error);
204    if (resattr == DW_DLV_ERROR) {
205	return resattr;
206    }
207    if (resattr == DW_DLV_OK) {
208	int cres;
209	char *cdir;
210
211	cres = dwarf_formstring(comp_dir_attr, &cdir, error);
212	if (cres == DW_DLV_ERROR) {
213	    return cres;
214	} else if (cres == DW_DLV_OK) {
215	    comp_dir = (Dwarf_Small *) cdir;
216	}
217    }
218    if (resattr == DW_DLV_OK) {
219	dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR);
220    }
221
222    dwarf_init_line_table_prefix(&prefix);
223    {
224	Dwarf_Small *line_ptr_out = 0;
225	int dres = dwarf_read_line_table_prefix(dbg,
226						line_ptr,
227						dbg->
228						de_debug_line_size -
229						line_offset,
230						&line_ptr_out,
231						&prefix, error);
232
233	if (dres == DW_DLV_ERROR) {
234	    dwarf_free_line_table_prefix(&prefix);
235	    return dres;
236	}
237	if (dres == DW_DLV_NO_ENTRY) {
238	    dwarf_free_line_table_prefix(&prefix);
239	    return dres;
240	}
241	line_ptr_end = prefix.pf_line_ptr_end;
242	line_ptr = line_ptr_out;
243    }
244
245
246
247    printf("total line info length %ld bytes, "
248	   "line offset 0x%llx %lld\n",
249	   (long) prefix.pf_total_length,
250	   (long long) line_offset, (long long) line_offset);
251    printf("compilation_directory %s\n",
252	   comp_dir ? ((char *) comp_dir) : "");
253
254    printf("  min instruction length %d\n",
255	   (int) prefix.pf_minimum_instruction_length);
256    printf("  default is stmt        %d\n", (int)
257	   prefix.pf_default_is_stmt);
258    printf("  line base              %d\n", (int)
259	   prefix.pf_line_base);
260    printf("  line_range             %d\n", (int)
261	   prefix.pf_line_range);
262
263
264    for (i = 1; i < prefix.pf_opcode_base; i++) {
265	printf("  opcode[%d] length %d\n", (int) i,
266	       (int) prefix.pf_opcode_length_table[i - 1]);
267    }
268
269    for (i = 0; i < prefix.pf_include_directories_count; ++i) {
270	printf("  include dir[%d] %s\n",
271	       (int) i, prefix.pf_include_directories[i]);
272    }
273
274
275    for (i = 0; i < prefix.pf_files_count; ++i) {
276	struct Line_Table_File_Entry_s *lfile =
277	    prefix.pf_line_table_file_entries + i;
278
279	Dwarf_Unsigned tlm2 = lfile->lte_last_modification_time;
280	Dwarf_Unsigned di = lfile->lte_directory_index;
281	Dwarf_Unsigned fl = lfile->lte_length_of_file;
282
283	printf("  file[%d]  %s\n",
284	       (int) i, (char *) lfile->lte_filename);
285
286	printf("    dir index %d\n", (int) di);
287	{
288	    time_t tt = (time_t) tlm2;
289
290	    printf("    last time 0x%x %s",	/* ctime supplies
291						   newline */
292		   (unsigned) tlm2, ctime(&tt));
293	}
294	printf("    file length %ld 0x%lx\n",
295	       (long) fl, (unsigned long) fl);
296
297
298    }
299
300
301    {
302	unsigned long long offset = line_ptr - orig_line_ptr;
303
304	printf("  statement prog offset in section: %llu 0x%llx\n",
305	       offset, offset);
306    }
307
308    /* Initialize the part of the state machine dependent on the
309       prefix.  */
310    is_stmt = prefix.pf_default_is_stmt;
311
312
313    print_line_header();
314    /* Start of statement program.  */
315    while (line_ptr < line_ptr_end) {
316	int type;
317
318	printf(" [0x%06llx] ", (long long) (line_ptr - orig_line_ptr));
319	opcode = *(Dwarf_Small *) line_ptr;
320	line_ptr++;
321	/* 'type' is the output */
322	WHAT_IS_OPCODE(type, opcode, prefix.pf_opcode_base,
323		       prefix.pf_opcode_length_table, line_ptr,
324		       prefix.pf_std_op_count);
325
326	if (type == LOP_DISCARD) {
327	    int oc;
328	    int opcnt = prefix.pf_opcode_length_table[opcode];
329
330	    printf(" DISCARD standard opcode %d with %d operands: "
331		   "not understood:", opcode, opcnt);
332	    for (oc = 0; oc < opcnt; oc++) {
333		/*
334		 * Read and discard operands we don't
335		 * understand.
336		 * Arbitrary choice of unsigned read.
337		 * Signed read would work as well.
338		 */
339		Dwarf_Unsigned utmp2;
340
341		DECODE_LEB128_UWORD(line_ptr, utmp2)
342		    printf(" %llu (0x%llx)",
343			   (unsigned long long) utmp2,
344			   (unsigned long long) utmp2);
345	    }
346
347	    printf("\n");
348	    /* do nothing, necessary ops done */
349	} else if (type == LOP_SPECIAL) {
350	    /* This op code is a special op in the object, no matter
351	       that it might fall into the standard op range in this
352	       compile Thatis, these are special opcodes between
353	       special_opcode_base and MAX_LINE_OP_CODE.  (including
354	       special_opcode_base and MAX_LINE_OP_CODE) */
355	    char special[50];
356	    unsigned origop = opcode;
357
358	    opcode = opcode - prefix.pf_opcode_base;
359	    address = address + prefix.pf_minimum_instruction_length *
360		(opcode / prefix.pf_line_range);
361	    line =
362		line + prefix.pf_line_base +
363		opcode % prefix.pf_line_range;
364
365	    sprintf(special, "Specialop %3u", origop);
366	    print_line_detail(special,
367			      opcode, address, (int) file, line, column,
368			      is_stmt, basic_block, end_sequence,
369			      prologue_end, epilogue_begin, isa);
370
371	    basic_block = false;
372
373	} else if (type == LOP_STANDARD) {
374	    switch (opcode) {
375
376	    case DW_LNS_copy:{
377
378		    print_line_detail("DW_LNS_copy",
379				      opcode, address, file, line,
380				      column, is_stmt, basic_block,
381				      end_sequence, prologue_end,
382				      epilogue_begin, isa);
383
384		    basic_block = false;
385		    break;
386		}
387
388	    case DW_LNS_advance_pc:{
389		    Dwarf_Unsigned utmp2;
390
391
392		    DECODE_LEB128_UWORD(line_ptr, utmp2)
393			printf("DW_LNS_advance_pc val %lld 0x%llx\n",
394			       (long long) (Dwarf_Word) utmp2,
395			       (long long) (Dwarf_Word) utmp2);
396		    leb128_num = (Dwarf_Word) utmp2;
397		    address =
398			address +
399			prefix.pf_minimum_instruction_length *
400			leb128_num;
401		    break;
402		}
403
404	    case DW_LNS_advance_line:{
405		    Dwarf_Signed stmp;
406
407
408		    DECODE_LEB128_SWORD(line_ptr, stmp)
409			advance_line = (Dwarf_Sword) stmp;
410		    printf("DW_LNS_advance_line val %lld 0x%llx\n",
411			   (long long) advance_line,
412			   (long long) advance_line);
413		    line = line + advance_line;
414		    break;
415		}
416
417	    case DW_LNS_set_file:{
418		    Dwarf_Unsigned utmp2;
419
420
421		    DECODE_LEB128_UWORD(line_ptr, utmp2)
422			file = (Dwarf_Word) utmp2;
423		    printf("DW_LNS_set_file  %ld\n", (long) file);
424		    break;
425		}
426
427	    case DW_LNS_set_column:{
428		    Dwarf_Unsigned utmp2;
429
430
431		    DECODE_LEB128_UWORD(line_ptr, utmp2)
432			column = (Dwarf_Word) utmp2;
433		    printf("DW_LNS_set_column val %lld 0x%llx\n",
434			   (long long) column, (long long) column);
435		    break;
436		}
437
438	    case DW_LNS_negate_stmt:{
439		    is_stmt = !is_stmt;
440		    printf("DW_LNS_negate_stmt\n");
441		    break;
442		}
443
444	    case DW_LNS_set_basic_block:{
445
446		    printf("DW_LNS_set_basic_block\n");
447		    basic_block = true;
448		    break;
449		}
450
451	    case DW_LNS_const_add_pc:{
452		    opcode = MAX_LINE_OP_CODE - prefix.pf_opcode_base;
453		    address =
454			address +
455			prefix.pf_minimum_instruction_length * (opcode /
456								prefix.
457								pf_line_range);
458
459		    printf("DW_LNS_const_add_pc new address 0x%llx\n",
460			   (long long) address);
461		    break;
462		}
463
464	    case DW_LNS_fixed_advance_pc:{
465
466		    READ_UNALIGNED(dbg, fixed_advance_pc, Dwarf_Half,
467				   line_ptr, sizeof(Dwarf_Half));
468		    line_ptr += sizeof(Dwarf_Half);
469		    address = address + fixed_advance_pc;
470		    printf("DW_LNS_fixed_advance_pc val %lld 0x%llx"
471			   " new address 0x%llx\n",
472			   (long long) fixed_advance_pc,
473			   (long long) fixed_advance_pc,
474			   (long long) address);
475		    break;
476		}
477	    case DW_LNS_set_prologue_end:{
478
479		    prologue_end = true;
480		    printf("DW_LNS_set_prologue_end set true.\n");
481		    break;
482
483
484		}
485		/* New in DWARF3 */
486	    case DW_LNS_set_epilogue_begin:{
487		    epilogue_begin = true;
488		    printf("DW_LNS_set_epilogue_begin set true.\n");
489		    break;
490		}
491
492		/* New in DWARF3 */
493	    case DW_LNS_set_isa:{
494		    Dwarf_Unsigned utmp2;
495
496		    DECODE_LEB128_UWORD(line_ptr, utmp2)
497			isa = utmp2;
498		    printf("DW_LNS_set_isa new value 0x%llx.\n",
499			   (unsigned long long) utmp2);
500		    if (isa != utmp2) {
501			/* The value of the isa did not fit in our
502			   local so we record it wrong. declare an
503			   error. */
504			dwarf_free_line_table_prefix(&prefix);
505
506			_dwarf_error(dbg, error,
507				     DW_DLE_LINE_NUM_OPERANDS_BAD);
508			return (DW_DLV_ERROR);
509		    }
510		    break;
511		}
512	    }
513
514
515	} else if (type == LOP_EXTENDED) {
516	    Dwarf_Unsigned utmp3 = 0;
517	    Dwarf_Word instr_length = 0;
518	    Dwarf_Small ext_opcode = 0;
519
520	    DECODE_LEB128_UWORD(line_ptr, utmp3)
521		instr_length = (Dwarf_Word) utmp3;
522	    ext_opcode = *(Dwarf_Small *) line_ptr;
523	    line_ptr++;
524	    switch (ext_opcode) {
525
526	    case DW_LNE_end_sequence:{
527		    end_sequence = true;
528
529		    print_line_detail("DW_LNE_end_sequence extended",
530				      opcode, address, file, line,
531				      column, is_stmt, basic_block,
532				      end_sequence, prologue_end,
533				      epilogue_begin, isa);
534
535		    address = 0;
536		    file = 1;
537		    line = 1;
538		    column = 0;
539		    is_stmt = prefix.pf_default_is_stmt;
540		    basic_block = false;
541		    end_sequence = false;
542		    prologue_end = false;
543		    epilogue_begin = false;
544
545
546		    break;
547		}
548
549	    case DW_LNE_set_address:{
550		    if (instr_length - 1 == dbg->de_pointer_size) {
551			READ_UNALIGNED(dbg, address, Dwarf_Addr,
552				       line_ptr, dbg->de_pointer_size);
553
554			line_ptr += dbg->de_pointer_size;
555			printf("DW_LNE_set_address address 0x%llx\n",
556			       (long long) address);
557		    } else {
558			dwarf_free_line_table_prefix(&prefix);
559			_dwarf_error(dbg, error,
560				     DW_DLE_LINE_SET_ADDR_ERROR);
561			return (DW_DLV_ERROR);
562		    }
563
564		    break;
565		}
566
567	    case DW_LNE_define_file:{
568
569
570		    Dwarf_Small *fn;
571		    Dwarf_Unsigned di;
572		    Dwarf_Unsigned tlm;
573		    Dwarf_Unsigned fl;
574
575		    fn = (Dwarf_Small *) line_ptr;
576		    line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
577
578		    di = _dwarf_decode_u_leb128(line_ptr,
579						&leb128_length);
580		    line_ptr = line_ptr + leb128_length;
581
582		    tlm = _dwarf_decode_u_leb128(line_ptr,
583						 &leb128_length);
584		    line_ptr = line_ptr + leb128_length;
585
586		    fl = _dwarf_decode_u_leb128(line_ptr,
587						&leb128_length);
588		    line_ptr = line_ptr + leb128_length;
589
590
591		    printf("DW_LNE_define_file %s \n", fn);
592		    printf("    dir index %d\n", (int) di);
593		    {
594			time_t tt3 = (time_t) tlm;
595
596			/* ctime supplies newline */
597			printf("    last time 0x%x %s",
598			       (unsigned) tlm, ctime(&tt3));
599		    }
600		    printf("    file length %ld 0x%lx\n",
601			   (long) fl, (unsigned long) fl);
602
603		    break;
604		}
605
606	    default:{
607		    dwarf_free_line_table_prefix(&prefix);
608		    _dwarf_error(dbg, error,
609				 DW_DLE_LINE_EXT_OPCODE_BAD);
610		    return (DW_DLV_ERROR);
611		}
612	    }
613
614	}
615    }
616
617    dwarf_free_line_table_prefix(&prefix);
618    return (DW_DLV_OK);
619}
620
621/*
622	Caller passes in compilation unit DIE.
623*/
624int
625_dwarf_print_lines(Dwarf_Die die, Dwarf_Error * error)
626{
627    int res;
628
629    res = _dwarf_internal_printlines(die, error);
630    if (res != DW_DLV_OK) {
631	return res;
632    }
633    return res;
634}
635