1 /*
2 Copyright (C) 2000,2002,2004,2005,2006 Silicon Graphics, Inc. All Rights Reserved.
3 Portions Copyright (C) 2007-2020 David Anderson. All Rights Reserved.
4 Portions Copyright 2012 SN Systems Ltd. All rights reserved.
5
6 This program is free software; you can redistribute it
7 and/or modify it under the terms of version 2.1 of the
8 GNU Lesser General Public License as published by the Free
9 Software Foundation.
10
11 This program is distributed in the hope that it would be
12 useful, but WITHOUT ANY WARRANTY; without even the implied
13 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE.
15
16 Further, this software is distributed without any warranty
17 that it is free of the rightful claim of any third person
18 regarding infringement or the like. Any license provided
19 herein, whether implied or otherwise, applies only to this
20 software file. Patent licenses, if any, provided herein
21 do not apply to combinations of this program with other
22 software, or any other product whatsoever.
23
24 You should have received a copy of the GNU Lesser General
25 Public License along with this program; if not, write the
26 Free Software Foundation, Inc., 51 Franklin Street - Fifth
27 Floor, Boston MA 02110-1301, USA.
28
29 */
30
31 #include "config.h"
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <time.h>
35
36 #include "dwarf_incl.h"
37 #include "dwarf_alloc.h"
38 #include "dwarf_error.h"
39 #include "dwarf_util.h"
40 #include "dwarf_line.h"
41 #include "dwarfstring.h"
42
43 #define PRINTING_DETAILS 1
44
45 static void
print_line_header(Dwarf_Debug dbg,Dwarf_Bool is_single_tab,Dwarf_Bool is_actuals_tab)46 print_line_header(Dwarf_Debug dbg,
47 Dwarf_Bool is_single_tab,
48 Dwarf_Bool is_actuals_tab)
49 {
50 if (!is_single_tab) {
51 /* Ugly indenting follows, it makes lines shorter to see them better.
52 Best to use a wider text window to really see how it looks.*/
53 if (is_actuals_tab) {
54 _dwarf_printf(dbg,"\nActuals Table\n");
55 _dwarf_printf(dbg,
56 " be\n"
57 " ls\n"
58 " ce\n"
59 " section op kq\n"
60 " offset code address/index row isa ??\n");
61 return;
62 } else {
63 _dwarf_printf(dbg,"\nLogicals Table\n");
64 _dwarf_printf(dbg,
65 " s pe\n"
66 " tirp\n"
67 " msoi\n"
68 " section op tall\n"
69 " offset row code address/indx fil lne col disc cntx subp ????\n");
70 return;
71 }
72 }
73
74 /* Single level table */
75 _dwarf_printf(dbg,
76 " s b e p e i d\n"
77 " t l s r p s i\n"
78 " m c e o i a s\n"
79 " section op col t k q l l c\n"
80 " offset code address file line umn ? ? ? ? ?\n");
81 } /* End of function with ugly indenting. */
82
83 static void
print_line_detail(Dwarf_Debug dbg,const char * prefix,int opcode,unsigned curr_line,struct Dwarf_Line_Registers_s * regs,Dwarf_Bool is_single_table,Dwarf_Bool is_actuals_table)84 print_line_detail(
85 Dwarf_Debug dbg,
86 const char *prefix,
87 int opcode,
88 unsigned curr_line,
89 struct Dwarf_Line_Registers_s * regs,
90 Dwarf_Bool is_single_table, Dwarf_Bool is_actuals_table)
91 {
92 dwarfstring m1;
93
94 dwarfstring_constructor(&m1);
95 if(!is_single_table && is_actuals_table) {
96 dwarfstring_append_printf_s(&m1,"%-15s ",(char *)prefix);
97 dwarfstring_append_printf_i(&m1,"%3d ",opcode);
98 dwarfstring_append_printf_u(&m1,"0x%" DW_PR_XZEROS DW_PR_DUx ,
99 regs->lr_address);
100 dwarfstring_append_printf_u(&m1,"/%01u",regs->lr_op_index);
101 dwarfstring_append_printf_u(&m1," %5lu", regs->lr_line);
102 dwarfstring_append_printf_u(&m1," %3d",regs->lr_isa);
103 dwarfstring_append_printf_i(&m1," %1d", regs->lr_basic_block);
104 dwarfstring_append_printf_i(&m1,"%1d\n", regs->lr_end_sequence);
105 _dwarf_printf(dbg,dwarfstring_string(&m1));
106 dwarfstring_destructor(&m1);
107 return;
108 }
109 if(!is_single_table && !is_actuals_table) {
110 dwarfstring_append_printf_i(&m1,
111 "[%3d] " /* row number */, curr_line);
112 dwarfstring_append_printf_s(&m1,
113 "%-15s ",(char *)prefix);
114 dwarfstring_append_printf_i(&m1,
115 "%3d ",opcode);
116 dwarfstring_append_printf_u(&m1,
117 "x%" DW_PR_XZEROS DW_PR_DUx, regs->lr_address);
118 dwarfstring_append_printf_u(&m1,
119 "/%01u", regs->lr_op_index);
120 dwarfstring_append_printf_u(&m1," %2lu ",regs->lr_file);
121 dwarfstring_append_printf_u(&m1,"%4lu ",regs->lr_line);
122 dwarfstring_append_printf_u(&m1,"%1lu",regs->lr_column);
123 if (regs->lr_discriminator ||
124 regs->lr_prologue_end ||
125 regs->lr_epilogue_begin ||
126 regs->lr_isa ||
127 regs->lr_is_stmt ||
128 regs->lr_call_context ||
129 regs->lr_subprogram) {
130 dwarfstring_append_printf_u(&m1,
131 " x%02" DW_PR_DUx ,
132 regs->lr_discriminator); /* DWARF4 */
133 dwarfstring_append_printf_u(&m1,
134 " x%02" DW_PR_DUx , regs->lr_call_context); /* EXPERIMENTAL */
135 dwarfstring_append_printf_u(&m1,
136 " x%02" DW_PR_DUx , regs->lr_subprogram); /* EXPERIMENTAL */
137 dwarfstring_append_printf_i(&m1,
138 " %1d", regs->lr_is_stmt);
139 dwarfstring_append_printf_i(&m1,
140 "%1d", (int) regs->lr_isa);
141 dwarfstring_append_printf_i(&m1,
142 "%1d", regs->lr_prologue_end); /* DWARF3 */
143 dwarfstring_append_printf_i(&m1,
144 "%1d", regs->lr_epilogue_begin); /* DWARF3 */
145 }
146 dwarfstring_append(&m1,"\n");
147 _dwarf_printf(dbg,dwarfstring_string(&m1));
148 dwarfstring_destructor(&m1);
149 return;
150 }
151 /* In the first quoted line below:
152 3d looks better than 2d, but best to do that as separate
153 change and test from two-level-line-tables. */
154 dwarfstring_append_printf_s(&m1,
155 "%-15s ",(char *)prefix);
156 dwarfstring_append_printf_i(&m1,
157 "%2d ",opcode);
158 dwarfstring_append_printf_u(&m1,
159 "0x%" DW_PR_XZEROS DW_PR_DUx " ",
160 regs->lr_address);
161 dwarfstring_append_printf_u(&m1,
162 "%2lu ", regs->lr_file);
163 dwarfstring_append_printf_u(&m1,
164 "%4lu ", regs->lr_line);
165 dwarfstring_append_printf_u(&m1,
166 "%2lu ", regs->lr_column);
167 dwarfstring_append_printf_i(&m1,
168 "%1d ",regs->lr_is_stmt);
169 dwarfstring_append_printf_i(&m1,
170 "%1d ", regs->lr_basic_block);
171 dwarfstring_append_printf_i(&m1,
172 "%1d",regs->lr_end_sequence);
173 if (regs->lr_discriminator ||
174 regs->lr_prologue_end ||
175 regs->lr_epilogue_begin ||
176 regs->lr_isa) {
177 dwarfstring_append_printf_i(&m1,
178 " %1d", regs->lr_prologue_end); /* DWARF3 */
179 dwarfstring_append_printf_i(&m1,
180 " %1d", regs->lr_epilogue_begin); /* DWARF3 */
181 dwarfstring_append_printf_i(&m1,
182 " %1d", regs->lr_isa); /* DWARF3 */
183 dwarfstring_append_printf_u(&m1,
184 " 0x%" DW_PR_DUx , regs->lr_discriminator); /* DWARF4 */
185 }
186 dwarfstring_append(&m1, "\n");
187 _dwarf_printf(dbg,dwarfstring_string(&m1));
188 dwarfstring_destructor(&m1);
189 }
190
191
192 #include "dwarf_line_table_reader_common.h"
193
194
195 static void
print_include_directory_details(Dwarf_Debug dbg,unsigned int line_version,Dwarf_Line_Context line_context)196 print_include_directory_details(Dwarf_Debug dbg,
197 unsigned int line_version,
198 Dwarf_Line_Context line_context)
199 {
200 Dwarf_Unsigned u = 0;
201 dwarfstring m4;
202
203 dwarfstring_constructor(&m4);
204 if (line_version == DW_LINE_VERSION5) {
205 unsigned i = 0;
206 unsigned dfcount = line_context->lc_directory_entry_format_count;
207 dwarfstring_constructor(&m4);
208 dwarfstring_append_printf_u(&m4,
209 " directory entry format count %u\n",dfcount);
210 _dwarf_printf(dbg,dwarfstring_string(&m4));
211 dwarfstring_reset(&m4);
212 for ( ; i < dfcount;++i) {
213 struct Dwarf_Unsigned_Pair_s *valpair = 0;
214 const char *tname = 0;
215 const char *fname = 0;
216 int res;
217
218 valpair = line_context->lc_directory_format_values +i;
219 dwarfstring_append_printf_u(&m4,
220 " format [%2u] ",i);
221 res = dwarf_get_LNCT_name(valpair->up_first,
222 &tname);
223 if ( res != DW_DLV_OK) {
224 tname = "<unknown type>";
225 }
226 dwarfstring_append_printf_u (&m4,
227 " type 0x%" DW_PR_XZEROS DW_PR_DUx ,valpair->up_first);
228 dwarfstring_append_printf_s (&m4,
229 " %-20s\n",(char *)tname);
230 res = dwarf_get_FORM_name(valpair->up_second,&fname);
231 if ( res != DW_DLV_OK) {
232 fname = "<unknown form>";
233 }
234 dwarfstring_append_printf_u(&m4,
235 " code 0x%" DW_PR_XZEROS DW_PR_DUx ,
236 valpair->up_second);
237 dwarfstring_append_printf_s(&m4,
238 " %-20s\n", (char *)fname);
239 _dwarf_printf(dbg,dwarfstring_string(&m4));
240 dwarfstring_reset(&m4);
241
242 }
243 }
244 /* common print of the files */
245 dwarfstring_append_printf_i(&m4,
246 " include directories count %d\n",
247 (int) line_context->lc_include_directories_count);
248 _dwarf_printf(dbg,dwarfstring_string(&m4));
249 dwarfstring_reset(&m4);
250 for (u = 0; u < line_context->lc_include_directories_count; ++u) {
251 dwarfstring_append_printf_u(&m4,
252 " include dir[%u] ",u);
253 dwarfstring_append_printf_s(&m4,
254 "%s\n",
255 (char *)line_context->lc_include_directories[u]);
256 _dwarf_printf(dbg,dwarfstring_string(&m4));
257 dwarfstring_reset(&m4);
258 }
259 dwarfstring_destructor(&m4);
260 }
261
262 static void
print_just_file_entry_details(Dwarf_Debug dbg,Dwarf_Line_Context line_context)263 print_just_file_entry_details(Dwarf_Debug dbg,
264 Dwarf_Line_Context line_context)
265 {
266 unsigned fiu = 0;
267 Dwarf_File_Entry fe = line_context->lc_file_entries;
268 Dwarf_File_Entry fe2 = fe;
269 dwarfstring m3;
270
271 dwarfstring_constructor(&m3);
272 dwarfstring_append_printf_i(&m3,
273 " file names count %d\n",
274 line_context->lc_file_entry_count);
275 _dwarf_printf(dbg,dwarfstring_string(&m3));
276 dwarfstring_reset(&m3);
277 for (fiu = 0 ; fe2 ; fe2 = fe->fi_next,++fiu ) {
278 Dwarf_Unsigned tlm2 = 0;
279 unsigned filenum = 0;
280
281 fe = fe2;
282 tlm2 = fe->fi_time_last_mod;
283 filenum = fiu+1;
284
285 /* The space character at the end of line is silly,
286 but lets leave it there for the moment to avoid
287 changing output. */
288 if (line_context->lc_file_entry_count > 9) {
289 dwarfstring_append_printf_u(&m3,
290 " file[%2u] ",fiu);
291 dwarfstring_append_printf_s(&m3,
292 "%-20s ",
293 (char *) fe->fi_file_name);
294 dwarfstring_append_printf_u(&m3,
295 "(file-number: %u)\n",
296 filenum);
297 } else {
298 dwarfstring_append_printf_u(&m3,
299 " file[%u] ", fiu);
300 dwarfstring_append_printf_s(&m3,
301 "%-20s ",(char *)fe->fi_file_name);
302 dwarfstring_append_printf_u(&m3,
303 "(file-number: %u)\n",filenum);
304 }
305 _dwarf_printf(dbg,dwarfstring_string(&m3));
306 dwarfstring_reset(&m3);
307 if (fe->fi_dir_index_present) {
308 Dwarf_Unsigned di = 0;
309 di = fe->fi_dir_index;
310 dwarfstring_append_printf_i(&m3,
311 " dir index %d\n", di);
312 }
313 if (fe->fi_time_last_mod_present) {
314 time_t tt = (time_t) tlm2;
315
316 /* ctime supplies newline */
317 dwarfstring_append_printf_u(&m3,
318 " last time 0x%x ",tlm2);
319 dwarfstring_append(&m3,(char *)ctime(&tt));
320 }
321 if (fe->fi_file_length_present) {
322 Dwarf_Unsigned fl = 0;
323
324 fl = fe->fi_file_length;
325 dwarfstring_append_printf_i(&m3,
326 " file length %ld ",fl);
327 dwarfstring_append_printf_u(&m3,
328 "0x%lx\n",fl);
329 }
330 if (fe->fi_md5_present) {
331 char *c = (char *)&fe->fi_md5_value;
332 char *end = c+sizeof(fe->fi_md5_value);
333 dwarfstring_append(&m3, " file md5 value 0x");
334 while(c < end) {
335 dwarfstring_append_printf_u(&m3,
336 "%02x",0xff&*c);
337 ++c;
338 }
339 dwarfstring_append(&m3,"\n");
340 }
341 if (dwarfstring_strlen(&m3)) {
342 _dwarf_printf(dbg,dwarfstring_string(&m3));
343 dwarfstring_reset(&m3);
344 }
345 }
346 dwarfstring_destructor(&m3);
347 }
348
349 static void
print_file_entry_details(Dwarf_Debug dbg,unsigned int line_version,Dwarf_Line_Context line_context)350 print_file_entry_details(Dwarf_Debug dbg,
351 unsigned int line_version,
352 Dwarf_Line_Context line_context)
353 {
354 dwarfstring m5;
355
356 dwarfstring_constructor(&m5);
357 if (line_version == DW_LINE_VERSION5) {
358 unsigned i = 0;
359 unsigned dfcount = line_context->lc_file_name_format_count;
360
361 dwarfstring_append_printf_u(&m5,
362 " file entry format count %u\n",dfcount);
363 for ( ; i < dfcount;++i) {
364 struct Dwarf_Unsigned_Pair_s *valpair = 0;
365 const char *tname = 0;
366 const char *fname = 0;
367 int res;
368
369 valpair = line_context->lc_file_format_values +i;
370 dwarfstring_append_printf_u(&m5,
371 " format [%2u] ",i);
372 res = dwarf_get_LNCT_name(valpair->up_first,&tname);
373 if ( res != DW_DLV_OK) {
374 tname = "<unknown type>";
375 }
376 dwarfstring_append_printf_u(&m5,
377 " type 0x%" DW_PR_XZEROS DW_PR_DUx,
378 valpair->up_first);
379 dwarfstring_append_printf_s(&m5,
380 " %-20s\n",(char *)tname);
381 res = dwarf_get_FORM_name(valpair->up_second,&fname);
382 if ( res != DW_DLV_OK) {
383 fname = "<unknown form>";
384 }
385 dwarfstring_append_printf_u(&m5,
386 " code 0x%"
387 DW_PR_XZEROS DW_PR_DUx,
388 valpair->up_second);
389 dwarfstring_append_printf_s(&m5, " %-20s\n",
390 (char *)fname);
391 _dwarf_printf(dbg,dwarfstring_string(&m5));
392 dwarfstring_reset(&m5);
393 }
394 dwarfstring_destructor(&m5);
395 print_just_file_entry_details(dbg,line_context);
396 } else {
397 print_just_file_entry_details(dbg,line_context);
398 dwarfstring_destructor(&m5);
399 }
400
401 }
402
403 static void
print_experimental_subprograms_list(Dwarf_Debug dbg,Dwarf_Line_Context line_context)404 print_experimental_subprograms_list(Dwarf_Debug dbg,
405 Dwarf_Line_Context line_context)
406 {
407 /* Print the subprograms list. */
408 Dwarf_Unsigned count = line_context->lc_subprogs_count;
409 Dwarf_Unsigned exu = 0;
410 Dwarf_Subprog_Entry sub = line_context->lc_subprogs;
411 dwarfstring m6;
412
413 dwarfstring_constructor(&m6);
414 dwarfstring_append_printf_u(&m6,
415 " subprograms count %" DW_PR_DUu "\n",count);
416 if (count > 0) {
417 dwarfstring_append(&m6," indx file line name\n");
418 }
419 _dwarf_printf(dbg,dwarfstring_string(&m6));
420 dwarfstring_reset(&m6);
421 for (exu = 0 ; exu < count ; exu++,sub++) {
422 dwarfstring_append_printf_u(&m6,
423 " [%2" DW_PR_DUu,exu+1);
424 dwarfstring_append_printf_u(&m6,
425 "] %4" DW_PR_DUu,sub->ds_decl_file);
426 dwarfstring_append_printf_u(&m6,
427 " %4" DW_PR_DUu ,sub->ds_decl_line);
428 dwarfstring_append_printf_s(&m6,
429 " %s\n",(char *)sub->ds_subprog_name);
430 _dwarf_printf(dbg,dwarfstring_string(&m6));
431 dwarfstring_reset(&m6);
432 }
433 dwarfstring_destructor(&m6);
434 }
435
436 static void
437 do_line_print_now(Dwarf_Debug dbg,int line_version,
438 Dwarf_Small * comp_dir,
439 Dwarf_Line_Context line_context) ;
440 static void print_experimental_counts(Dwarf_Debug dbg,
441 int line_version,
442 Dwarf_Line_Context line_context);
443
444 static int print_actuals_and_locals(Dwarf_Debug dbg,
445 Dwarf_Line_Context line_context,
446 Dwarf_Unsigned bogus_bytes_count,
447 Dwarf_Small *bogus_bytes_ptr,
448 Dwarf_Small *orig_line_ptr,
449 Dwarf_Small *line_ptr,
450 Dwarf_Small *section_start,
451 Dwarf_Small *line_ptr_actuals,
452 Dwarf_Small *line_ptr_end,
453 Dwarf_Half address_size,
454 int * err_count_out,
455 Dwarf_Error *err);
456
457 /* return DW_DLV_OK if ok. else DW_DLV_NO_ENTRY or DW_DLV_ERROR
458 If err_count_out is non-NULL, this is a special 'check'
459 call. */
460 static int
_dwarf_internal_printlines(Dwarf_Die die,int * err_count_out,int only_line_header,Dwarf_Error * error)461 _dwarf_internal_printlines(Dwarf_Die die,
462 int * err_count_out,
463 int only_line_header,
464 Dwarf_Error * error)
465 {
466 /* This pointer is used to scan the portion of the .debug_line
467 section for the current cu. */
468 Dwarf_Small *line_ptr = 0;
469 Dwarf_Small *orig_line_ptr = 0;
470
471 /* Pointer to a DW_AT_stmt_list attribute in case it exists in the
472 die. */
473 Dwarf_Attribute stmt_list_attr = 0;
474
475 /* Pointer to DW_AT_comp_dir attribute in die. */
476 Dwarf_Attribute comp_dir_attr = 0;
477
478 /* Pointer to name of compilation directory. */
479 Dwarf_Small *comp_dir = NULL;
480
481 /* Offset into .debug_line specified by a DW_AT_stmt_list
482 attribute. */
483 Dwarf_Unsigned line_offset = 0;
484
485 /* These variables are used to decode leb128 numbers. Leb128_num
486 holds the decoded number, and leb128_length is its length in
487 bytes. */
488 Dwarf_Half attrform = 0;
489
490 /* In case there are wierd bytes 'after' the line table
491 prologue this lets us print something. This is a gcc
492 compiler bug and we expect the bytes count to be 12. */
493 Dwarf_Small* bogus_bytes_ptr = 0;
494 Dwarf_Unsigned bogus_bytes_count = 0;
495 Dwarf_Half address_size = 0;
496 Dwarf_Unsigned fission_offset = 0;
497 unsigned line_version = 0;
498
499
500 /* The Dwarf_Debug this die belongs to. */
501 Dwarf_Debug dbg = 0;
502 Dwarf_CU_Context cu_context = 0;
503 Dwarf_Line_Context line_context = 0;
504 int resattr = DW_DLV_ERROR;
505 int lres = DW_DLV_ERROR;
506 int res = DW_DLV_ERROR;
507 Dwarf_Small *line_ptr_actuals = 0;
508 Dwarf_Small *line_ptr_end = 0;
509 Dwarf_Small *section_start = 0;
510
511 /* ***** BEGIN CODE ***** */
512
513 if (error != NULL) {
514 *error = NULL;
515 }
516
517 CHECK_DIE(die, DW_DLV_ERROR);
518 cu_context = die->di_cu_context;
519 dbg = cu_context->cc_dbg;
520
521 res = _dwarf_load_section(dbg, &dbg->de_debug_line,error);
522 if (res != DW_DLV_OK) {
523 return res;
524 }
525 if (!dbg->de_debug_line.dss_size) {
526 return (DW_DLV_NO_ENTRY);
527 }
528
529 address_size = _dwarf_get_address_size(dbg, die);
530 resattr = dwarf_attr(die, DW_AT_stmt_list, &stmt_list_attr, error);
531 if (resattr != DW_DLV_OK) {
532 return resattr;
533 }
534 /* The list of relevant FORMs is small.
535 DW_FORM_data4, DW_FORM_data8, DW_FORM_sec_offset
536 */
537 lres = dwarf_whatform(stmt_list_attr,&attrform,error);
538 if (lres != DW_DLV_OK) {
539 dwarf_dealloc(dbg,stmt_list_attr, DW_DLA_ATTR);
540 return lres;
541 }
542 if (attrform != DW_FORM_data4 && attrform != DW_FORM_data8 &&
543 attrform != DW_FORM_sec_offset ) {
544 dwarf_dealloc(dbg,stmt_list_attr, DW_DLA_ATTR);
545 _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
546 return (DW_DLV_ERROR);
547 }
548 lres = dwarf_global_formref(stmt_list_attr, &line_offset, error);
549 if (lres != DW_DLV_OK) {
550 dwarf_dealloc(dbg,stmt_list_attr, DW_DLA_ATTR);
551 return lres;
552 }
553
554 if (line_offset >= dbg->de_debug_line.dss_size) {
555 dwarf_dealloc(dbg,stmt_list_attr, DW_DLA_ATTR);
556 _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
557 return (DW_DLV_ERROR);
558 }
559 section_start = dbg->de_debug_line.dss_data;
560 {
561 Dwarf_Unsigned fission_size = 0;
562 int resfis = _dwarf_get_fission_addition_die(die, DW_SECT_LINE,
563 &fission_offset,&fission_size,error);
564 if(resfis != DW_DLV_OK) {
565 dwarf_dealloc(dbg,stmt_list_attr, DW_DLA_ATTR);
566 return resfis;
567 }
568 }
569
570 orig_line_ptr = section_start + line_offset + fission_offset;
571 line_ptr = orig_line_ptr;
572 dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR);
573
574 /* If die has DW_AT_comp_dir attribute, get the string that names
575 the compilation directory. */
576 resattr = dwarf_attr(die, DW_AT_comp_dir, &comp_dir_attr, error);
577 if (resattr == DW_DLV_ERROR) {
578 return resattr;
579 }
580 if (resattr == DW_DLV_OK) {
581 int cres = DW_DLV_ERROR;
582 char *cdir = 0;
583
584 cres = dwarf_formstring(comp_dir_attr, &cdir, error);
585 if (cres == DW_DLV_ERROR) {
586 return cres;
587 } else if (cres == DW_DLV_OK) {
588 comp_dir = (Dwarf_Small *) cdir;
589 }
590 }
591 if (resattr == DW_DLV_OK) {
592 dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR);
593 }
594 line_context = (Dwarf_Line_Context)
595 _dwarf_get_alloc(dbg, DW_DLA_LINE_CONTEXT, 1);
596 if (line_context == NULL) {
597 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
598 return (DW_DLV_ERROR);
599 }
600 {
601 Dwarf_Small *newlinep = 0;
602 int dres = _dwarf_read_line_table_header(dbg,
603 cu_context,
604 section_start,
605 line_ptr,
606 dbg->de_debug_line.dss_size,
607 &newlinep,
608 line_context,
609 &bogus_bytes_ptr,
610 &bogus_bytes_count,
611 error,
612 err_count_out);
613 if (dres == DW_DLV_ERROR) {
614 dwarf_srclines_dealloc_b(line_context);
615 return dres;
616 }
617 if (dres == DW_DLV_NO_ENTRY) {
618 dwarf_srclines_dealloc_b(line_context);
619 return dres;
620 }
621 line_ptr_end = line_context->lc_line_ptr_end;
622 line_ptr = newlinep;
623 if (line_context->lc_actuals_table_offset > 0) {
624 line_ptr_actuals = line_context->lc_line_prologue_start +
625 line_context->lc_actuals_table_offset;
626 }
627 }
628 line_version = line_context->lc_version_number;
629 line_context->lc_compilation_directory = comp_dir;
630 if (only_line_header) {
631 /* Just checking for header errors, nothing more here.*/
632 dwarf_srclines_dealloc_b(line_context);
633 return DW_DLV_OK;
634 }
635 do_line_print_now(dbg,line_version,comp_dir,line_context);
636 print_include_directory_details(dbg,line_version,line_context);
637 print_file_entry_details(dbg,line_version,line_context);
638 print_experimental_counts(dbg, line_version,line_context);
639 res = print_actuals_and_locals(dbg, line_context,
640 bogus_bytes_count,bogus_bytes_ptr,
641 orig_line_ptr,
642 line_ptr,
643 section_start,
644 line_ptr_actuals,
645 line_ptr_end,
646 address_size,
647 err_count_out,
648 error);
649 if (res != DW_DLV_OK) {
650 return res;
651 }
652 return DW_DLV_OK;
653 }
654
655 static void
do_line_print_now(Dwarf_Debug dbg,int line_version,Dwarf_Small * comp_dir,Dwarf_Line_Context line_context)656 do_line_print_now(Dwarf_Debug dbg,
657 int line_version,
658 Dwarf_Small *comp_dir,
659 Dwarf_Line_Context line_context)
660 {
661 dwarfstring m7;
662 Dwarf_Unsigned i = 0;
663
664 dwarfstring_constructor(&m7);
665 dwarfstring_append_printf_i(&m7,
666 "total line info length %ld bytes,",
667 line_context->lc_total_length);
668
669 dwarfstring_append_printf_u(&m7,
670 " line offset 0x%" DW_PR_XZEROS DW_PR_DUx,
671 line_context->lc_section_offset);
672
673 dwarfstring_append_printf_u(&m7,
674 " %" DW_PR_DUu "\n",
675 line_context->lc_section_offset);
676
677 if (line_version <= DW_LINE_VERSION5) {
678 dwarfstring_append_printf_i(&m7,
679 " line table version %d\n",
680 (int) line_context->lc_version_number);
681 } else {
682 dwarfstring_append_printf_u(&m7,
683 " line table version 0x%x\n",
684 (int) line_context->lc_version_number);
685 }
686 if (line_version == DW_LINE_VERSION5) {
687 dwarfstring_append_printf_i(&m7,
688 " address size %d\n",
689 line_context->lc_address_size);
690 dwarfstring_append_printf_i(&m7,
691 " segment selector size %d\n",
692 line_context->lc_segment_selector_size);
693 }
694 _dwarf_printf(dbg,dwarfstring_string(&m7));
695 dwarfstring_reset(&m7);
696 dwarfstring_append_printf_i(&m7,
697 " line table length field length %d\n",
698 line_context->lc_length_field_length);
699 dwarfstring_append_printf_i(&m7,
700 " prologue length %d\n",
701 line_context->lc_prologue_length);
702 dwarfstring_append_printf_s(&m7,
703 " compilation_directory %s\n",
704 comp_dir ? ((char *) comp_dir) : "");
705
706 dwarfstring_append_printf_i(&m7,
707 " min instruction length %d\n",
708 line_context->lc_minimum_instruction_length);
709 _dwarf_printf(dbg,dwarfstring_string(&m7));
710 dwarfstring_reset(&m7);
711 if (line_version == DW_LINE_VERSION5 ||
712 line_version == DW_LINE_VERSION4 ||
713 line_version == EXPERIMENTAL_LINE_TABLES_VERSION) {
714 dwarfstring_append_printf_u(&m7,
715 " maximum ops per instruction %u\n",
716 line_context->lc_maximum_ops_per_instruction);
717 _dwarf_printf(dbg,dwarfstring_string(&m7));
718 dwarfstring_reset(&m7);
719 }
720 if (line_version == EXPERIMENTAL_LINE_TABLES_VERSION) {
721 dwarfstring_append_printf_u(&m7, " actuals table offset "
722 "0x%" DW_PR_XZEROS DW_PR_DUx "\n",
723 line_context->lc_actuals_table_offset);
724 dwarfstring_append_printf_u(&m7," logicals table offset "
725 "0x%" DW_PR_XZEROS DW_PR_DUx "\n",
726 line_context->lc_logicals_table_offset);
727 _dwarf_printf(dbg,dwarfstring_string(&m7));
728 dwarfstring_reset(&m7);
729 }
730 dwarfstring_append_printf_i(&m7,
731 " default is stmt %d\n",
732 (int)line_context->lc_default_is_stmt);
733 dwarfstring_append_printf_i(&m7,
734 " line base %d\n",
735 (int)line_context->lc_line_base);
736 dwarfstring_append_printf_i(&m7,
737 " line_range %d\n",
738 (int)line_context->lc_line_range);
739 dwarfstring_append_printf_i(&m7,
740 " opcode base %d\n",
741 (int)line_context->lc_opcode_base);
742 dwarfstring_append_printf_i(&m7,
743 " standard opcode count %d\n",
744 (int)line_context->lc_std_op_count);
745 _dwarf_printf(dbg,dwarfstring_string(&m7));
746 dwarfstring_reset(&m7);
747
748 for (i = 1; i < line_context->lc_opcode_base; i++) {
749 dwarfstring_append_printf_i(&m7,
750 " opcode[%2d] length", (int) i);
751 dwarfstring_append_printf_i(&m7,
752 " %d\n",
753 (int) line_context->lc_opcode_length_table[i - 1]);
754 _dwarf_printf(dbg,dwarfstring_string(&m7));
755 dwarfstring_reset(&m7);
756 }
757 dwarfstring_destructor(&m7);
758 }
759
760 static void
print_experimental_counts(Dwarf_Debug dbg,int line_version,Dwarf_Line_Context line_context)761 print_experimental_counts(Dwarf_Debug dbg, int line_version,
762 Dwarf_Line_Context line_context)
763 {
764 if (line_version == EXPERIMENTAL_LINE_TABLES_VERSION) {
765 print_experimental_subprograms_list(dbg,line_context);
766 }
767 }
768
769 static int
print_actuals_and_locals(Dwarf_Debug dbg,Dwarf_Line_Context line_context,Dwarf_Unsigned bogus_bytes_count,Dwarf_Small * bogus_bytes_ptr,Dwarf_Small * orig_line_ptr,Dwarf_Small * line_ptr,Dwarf_Small * section_start,Dwarf_Small * line_ptr_actuals,Dwarf_Small * line_ptr_end,Dwarf_Half address_size,int * err_count_out,Dwarf_Error * error)770 print_actuals_and_locals(Dwarf_Debug dbg,
771 Dwarf_Line_Context line_context,
772 Dwarf_Unsigned bogus_bytes_count,
773 Dwarf_Small *bogus_bytes_ptr,
774 Dwarf_Small *orig_line_ptr,
775 Dwarf_Small *line_ptr,
776 Dwarf_Small *section_start,
777 Dwarf_Small *line_ptr_actuals,
778 Dwarf_Small *line_ptr_end,
779 Dwarf_Half address_size,
780 int * err_count_out,
781 Dwarf_Error *error)
782 {
783 int res = 0;
784 dwarfstring m8;
785 Dwarf_Unsigned offset = 0;
786
787 dwarfstring_constructor(&m8);
788 if (bogus_bytes_count > 0) {
789 Dwarf_Unsigned wcount = bogus_bytes_count;
790 Dwarf_Unsigned boffset = bogus_bytes_ptr - section_start;
791
792 dwarfstring_append_printf_u(&m8,
793 "*** DWARF CHECK: the line table prologue header_length "
794 " is %" DW_PR_DUu " too high, we pretend it is smaller.",
795 wcount);
796 dwarfstring_append_printf_u(&m8,
797 "Section offset: 0x%"
798 DW_PR_XZEROS DW_PR_DUx,
799 boffset);
800 dwarfstring_append_printf_u(&m8,
801 " (%" DW_PR_DUu ") ***\n",
802 boffset);
803 *err_count_out += 1;
804 }
805 offset = line_ptr - section_start;
806 dwarfstring_append_printf_u(&m8,
807 " statement prog offset in section: 0x%"
808 DW_PR_XZEROS DW_PR_DUx,
809 offset);
810 dwarfstring_append_printf_u(&m8,
811 " (%" DW_PR_DUu ")\n",
812 offset);
813 _dwarf_printf(dbg,dwarfstring_string(&m8));
814 dwarfstring_reset(&m8);
815
816 {
817 Dwarf_Bool doaddrs = false;
818 Dwarf_Bool dolines = true;
819
820 if (!line_ptr_actuals) {
821 /* Normal single level line table. */
822
823 Dwarf_Bool is_single_table = true;
824 Dwarf_Bool is_actuals_table = false;
825 print_line_header(dbg, is_single_table, is_actuals_table);
826 res = read_line_table_program(dbg,
827 line_ptr, line_ptr_end, orig_line_ptr,
828 section_start,
829 line_context,
830 address_size, doaddrs, dolines,
831 is_single_table,
832 is_actuals_table,
833 error,
834 err_count_out);
835 if (res != DW_DLV_OK) {
836 dwarfstring_destructor(&m8);
837 dwarf_srclines_dealloc_b(line_context);
838 return res;
839 }
840 } else {
841 Dwarf_Bool is_single_table = false;
842 Dwarf_Bool is_actuals_table = false;
843 if (line_context->lc_version_number !=
844 EXPERIMENTAL_LINE_TABLES_VERSION) {
845 dwarf_srclines_dealloc_b(line_context);
846 dwarfstring_destructor(&m8);
847 _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
848 return (DW_DLV_ERROR);
849 }
850 /* Read Logicals */
851 print_line_header(dbg, is_single_table, is_actuals_table);
852 res = read_line_table_program(dbg,
853 line_ptr, line_ptr_actuals, orig_line_ptr,
854 section_start,
855 line_context,
856 address_size, doaddrs, dolines,
857 is_single_table,
858 is_actuals_table,
859 error,err_count_out);
860 if (res != DW_DLV_OK) {
861 dwarfstring_destructor(&m8);
862 dwarf_srclines_dealloc_b(line_context);
863 return res;
864 }
865 if (line_context->lc_actuals_table_offset > 0) {
866 is_actuals_table = true;
867 /* Read Actuals */
868
869 print_line_header(dbg, is_single_table, is_actuals_table);
870 res = read_line_table_program(dbg,
871 line_ptr_actuals, line_ptr_end, orig_line_ptr,
872 section_start,
873 line_context,
874 address_size, doaddrs, dolines,
875 is_single_table,
876 is_actuals_table,
877 error,
878 err_count_out);
879 if (res != DW_DLV_OK) {
880 dwarfstring_destructor(&m8);
881 dwarf_srclines_dealloc_b(line_context);
882 return res;
883 }
884 }
885 }
886 }
887 dwarfstring_destructor(&m8);
888 dwarf_srclines_dealloc_b(line_context);
889 return DW_DLV_OK;
890 }
891
892
893
894 /* This is support for dwarfdump: making it possible
895 for clients wanting line detail info on stdout
896 to get that detail without including internal libdwarf
897 header information.
898 Caller passes in compilation unit DIE.
899 The _dwarf_ version is obsolete (though supported for
900 compatibility).
901 The dwarf_ version is preferred.
902 The functions are intentionally identical: having
903 _dwarf_print_lines call dwarf_print_lines might
904 better emphasize they are intentionally identical, but
905 that seemed slightly silly given how short the functions are.
906 Interface adds error_count (output value) February 2009.
907
908 These *print_lines() functions print two-level tables in full
909 even when the user is not asking for both (ie, when
910 the caller asked for dwarf_srclines().
911 It was an accident, but after a short reflection
912 this seems like a good idea for -vvv. */
913 int
dwarf_print_lines(Dwarf_Die die,Dwarf_Error * error,int * error_count)914 dwarf_print_lines(Dwarf_Die die,
915 Dwarf_Error * error,
916 int *error_count)
917 {
918 int only_line_header = 0;
919 int res = _dwarf_internal_printlines(die,
920 error_count,
921 only_line_header,error);
922 return res;
923 }
924 int
_dwarf_print_lines(Dwarf_Die die,Dwarf_Error * error)925 _dwarf_print_lines(Dwarf_Die die, Dwarf_Error * error)
926 {
927 int only_line_header = 0;
928 int err_count = 0;
929 int res = _dwarf_internal_printlines(die,
930 &err_count,
931 only_line_header,error);
932 /* No way to get error count back in this interface */
933 return res;
934 }
935
936 /* The check is in case we are not printing full line data,
937 this gets some of the issues noted with .debug_line,
938 but not all. Call dwarf_print_lines() to get all issues.
939 Intended for apps like dwarfdump.
940 dwarf_check_lineheader_b() new 14 April 2020.
941 */
942 int
dwarf_check_lineheader_b(Dwarf_Die die,int * err_count_out,Dwarf_Error * err)943 dwarf_check_lineheader_b(Dwarf_Die die, int *err_count_out,
944 Dwarf_Error *err)
945 {
946 int res = 0;
947
948 int only_line_header = 1;
949 res = _dwarf_internal_printlines(die,err_count_out,
950 only_line_header,err);
951 return res;
952 }
953
954 /* This is ugly, no way to detect errors. They get ignored.
955 see dwarf_check_lineheader_b() above. */
956 void
dwarf_check_lineheader(Dwarf_Die die,int * err_count_out)957 dwarf_check_lineheader(Dwarf_Die die, int *err_count_out)
958 {
959 int res = 0;
960 Dwarf_Error err = 0;
961
962 int only_line_header = 1;
963 res = _dwarf_internal_printlines(die,err_count_out,
964 only_line_header,&err);
965 if (res == DW_DLV_ERROR) {
966 Dwarf_CU_Context c = 0;
967 Dwarf_Debug dbg = 0;
968
969 c = die->di_cu_context;
970 if (!c) {
971 return;
972 }
973 dbg = c->cc_dbg;
974 dwarf_dealloc(dbg,err,DW_DLA_ERROR);
975 err = 0;
976 }
977 }
978