xref: /illumos-gate/usr/src/lib/libdwarf/common/dwarf_print_lines.c (revision 8119dad84d6416f13557b0ba8e2aaf9064cbcfd3)
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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