tools/elf4rom/libs/dwarf-20071209/dwarfdump/print_frames.c
changeset 34 92d87f2e53c2
equal deleted inserted replaced
33:1af5c1be89f8 34:92d87f2e53c2
       
     1 /* 
       
     2   Copyright (C) 2006 Silicon Graphics, Inc.  All Rights Reserved.
       
     3   Portions Copyright (C) 2007 David Anderson. 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 of the GNU General Public License as
       
     7   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 General Public License along
       
    21   with this program; if not, write the Free Software Foundation, Inc., 51
       
    22   Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
       
    23 
       
    24   Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
       
    25   Mountain View, CA 94043, or:
       
    26 
       
    27   http://www.sgi.com
       
    28 
       
    29   For further information regarding this notice, see:
       
    30 
       
    31   http://oss.sgi.com/projects/GenInfo/NoticeExplan
       
    32 
       
    33 
       
    34 
       
    35 $Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_frames.c,v 1.5 2006/06/14 20:34:02 davea Exp $ */
       
    36 
       
    37 /* The address of the Free Software Foundation is
       
    38    Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 
       
    39    Boston, MA 02110-1301, USA.
       
    40    SGI has moved from the Crittenden Lane address.
       
    41 */
       
    42 
       
    43 
       
    44 
       
    45 #include "globals.h"
       
    46 
       
    47 #include "print_frames.h"
       
    48 #include "dwconf.h"
       
    49 #include "esb.h"
       
    50 
       
    51 
       
    52 static void
       
    53   print_one_frame_reg_col(Dwarf_Debug dbg,
       
    54                           Dwarf_Unsigned rule_id,
       
    55 			  Dwarf_Small value_type,
       
    56 			  Dwarf_Unsigned reg_used,
       
    57 			  struct dwconf_s *config_data,
       
    58 			  Dwarf_Signed offset_relevant,
       
    59 			  Dwarf_Signed offset, Dwarf_Ptr block_ptr);
       
    60 
       
    61 /*
       
    62     Gather the fde print logic here so the control logic
       
    63     determining what FDE to print is clearer.
       
    64 */
       
    65 int
       
    66 print_one_fde(Dwarf_Debug dbg, Dwarf_Fde fde,
       
    67 	      Dwarf_Unsigned fde_index,
       
    68 	      Dwarf_Cie * cie_data,
       
    69 	      Dwarf_Signed cie_element_count,
       
    70 	      Dwarf_Half address_size, int is_eh,
       
    71 	      struct dwconf_s *config_data)
       
    72 {
       
    73     Dwarf_Addr j = 0;
       
    74     Dwarf_Addr low_pc = 0;
       
    75     Dwarf_Unsigned func_length = 0;
       
    76     Dwarf_Ptr fde_bytes = NULL;
       
    77     Dwarf_Unsigned fde_bytes_length = 0;
       
    78     Dwarf_Off cie_offset = 0;
       
    79     Dwarf_Signed cie_index = 0;
       
    80     Dwarf_Off fde_offset = 0;
       
    81     Dwarf_Signed eh_table_offset = 0;
       
    82     int fres = 0;
       
    83     int offres = 0;
       
    84     string temps = 0;
       
    85     Dwarf_Error err = 0;
       
    86     int printed_intro_addr = 0;
       
    87 
       
    88     fres = dwarf_get_fde_range(fde,
       
    89 			       &low_pc, &func_length,
       
    90 			       &fde_bytes,
       
    91 			       &fde_bytes_length,
       
    92 			       &cie_offset, &cie_index,
       
    93 			       &fde_offset, &err);
       
    94     if (fres == DW_DLV_ERROR) {
       
    95 	print_error(dbg, "dwarf_get_fde_range", fres, err);
       
    96     }
       
    97     if (fres == DW_DLV_NO_ENTRY) {
       
    98 	return DW_DLV_NO_ENTRY;
       
    99     }
       
   100     if (cu_name_flag &&
       
   101 	fde_offset_for_cu_low != DW_DLV_BADOFFSET &&
       
   102 	(fde_offset < fde_offset_for_cu_low ||
       
   103 	 fde_offset > fde_offset_for_cu_high)) {
       
   104 	return DW_DLV_NO_ENTRY;
       
   105     }
       
   106     /* eh_table_offset is IRIX ONLY. */
       
   107     fres = dwarf_get_fde_exception_info(fde, &eh_table_offset, &err);
       
   108     if (fres == DW_DLV_ERROR) {
       
   109 	print_error(dbg, "dwarf_get_fde_exception_info", fres, err);
       
   110     }
       
   111     temps = get_fde_proc_name(dbg, low_pc);
       
   112     printf
       
   113 	("<%3lld><%#llx:%#llx><%s><fde offset 0x%llx length: 0x%llx>",
       
   114 	 cie_index, low_pc, (low_pc + func_length),
       
   115 	 temps ? temps : "", fde_offset, fde_bytes_length);
       
   116 
       
   117 
       
   118     if (!is_eh) {
       
   119 	/* IRIX uses eh_table_offset. */
       
   120 	if (eh_table_offset == DW_DLX_NO_EH_OFFSET) {
       
   121 	    printf("<eh offset %s>\n", "none");
       
   122 	} else if (eh_table_offset == DW_DLX_EH_OFFSET_UNAVAILABLE) {
       
   123 	    printf("<eh offset %s>\n", "unknown");
       
   124 	} else {
       
   125 	    printf("<eh offset 0x%llx>\n", eh_table_offset);
       
   126 	}
       
   127     } else {
       
   128 	int ares = 0;
       
   129 	Dwarf_Small *data = 0;
       
   130 	Dwarf_Unsigned len = 0;
       
   131 
       
   132 	ares = dwarf_get_fde_augmentation_data(fde, &data, &len, &err);
       
   133 	if (ares == DW_DLV_NO_ENTRY) {
       
   134 	    /* do nothing. */
       
   135 	} else if (ares == DW_DLV_OK) {
       
   136 	    int k2;
       
   137 
       
   138 	    printf("<eh aug data len 0x%llx", (long long) len);
       
   139 	    for (k2 = 0; k2 < len; ++k2) {
       
   140 		if (k2 == 0) {
       
   141 		    printf(" bytes 0x");
       
   142 		}
       
   143 		printf("%02x ", (unsigned char) data[k2]);
       
   144 	    }
       
   145 	    printf(">");
       
   146 	}			/* else DW_DLV_ERROR, do nothing */
       
   147         printf("\n");
       
   148     }
       
   149     /* call dwarf_get_fde_info_for_reg() to get whole matrix */
       
   150 
       
   151     for (j = low_pc; j < low_pc + func_length; j++) {
       
   152 	Dwarf_Half k;
       
   153 
       
   154 	if (config_data->cf_interface_number == 3) {
       
   155 	    Dwarf_Signed reg = 0;
       
   156 	    Dwarf_Signed offset_relevant = 0;
       
   157 	    Dwarf_Small value_type = 0;
       
   158 	    Dwarf_Signed offset_or_block_len = 0;
       
   159 	    Dwarf_Signed offset = 0;
       
   160 	    Dwarf_Ptr block_ptr = 0;
       
   161 	    Dwarf_Addr row_pc = 0;
       
   162 
       
   163 	    int fires = dwarf_get_fde_info_for_cfa_reg3(fde,
       
   164 							j,
       
   165 							&value_type,
       
   166 							&offset_relevant,
       
   167 							&reg,
       
   168 							&offset_or_block_len,
       
   169 							&block_ptr,
       
   170 							&row_pc,
       
   171 							&err);
       
   172 
       
   173 	    offset = offset_or_block_len;
       
   174 	    if (fires == DW_DLV_ERROR) {
       
   175 		print_error(dbg,
       
   176 			    "dwarf_get_fde_info_for_reg", fires, err);
       
   177 	    }
       
   178 	    if (fires == DW_DLV_NO_ENTRY) {
       
   179 		continue;
       
   180 	    }
       
   181 	    if (row_pc != j) {
       
   182 		/* duplicate row */
       
   183 		continue;
       
   184 	    }
       
   185 	    if (!printed_intro_addr) {
       
   186 		printf("    %08llx:\t", j);
       
   187 		printed_intro_addr = 1;
       
   188 	    }
       
   189 	    print_one_frame_reg_col(dbg, config_data->cf_cfa_reg,
       
   190 				    value_type,
       
   191 				    reg,
       
   192 				    config_data,
       
   193 				    offset_relevant, offset, block_ptr);
       
   194 	}
       
   195 	for (k = 0; k < config_data->cf_table_entry_count; k++) {
       
   196 	    Dwarf_Signed reg = 0;
       
   197 	    Dwarf_Signed offset_relevant = 0;
       
   198 	    int fires = 0;
       
   199 	    Dwarf_Small value_type = 0;
       
   200 	    Dwarf_Ptr block_ptr = 0;
       
   201 	    Dwarf_Signed offset_or_block_len = 0;
       
   202 	    Dwarf_Signed offset = 0;
       
   203 	    Dwarf_Addr row_pc = 0;
       
   204 
       
   205 	    if (config_data->cf_interface_number == 3) {
       
   206 
       
   207 		fires = dwarf_get_fde_info_for_reg3(fde,
       
   208 						    k,
       
   209 						    j,
       
   210 						    &value_type,
       
   211 						    &offset_relevant,
       
   212 						    &reg,
       
   213 						    &offset_or_block_len,
       
   214 						    &block_ptr,
       
   215 						    &row_pc, &err);
       
   216 		offset = offset_or_block_len;
       
   217 	    } else {		/* ASSERT:
       
   218 				   config_data->cf_interface_number ==
       
   219 				   2 */
       
   220 
       
   221 
       
   222 		value_type = DW_EXPR_OFFSET;
       
   223 		fires = dwarf_get_fde_info_for_reg(fde,
       
   224 						   k,
       
   225 						   j,
       
   226 						   &offset_relevant,
       
   227 						   &reg,
       
   228 						   &offset, &row_pc,
       
   229 						   &err);
       
   230 	    }
       
   231 	    if (fires == DW_DLV_ERROR) {
       
   232                 printf("\n");
       
   233 		print_error(dbg,
       
   234 			    "dwarf_get_fde_info_for_reg", fires, err);
       
   235 	    }
       
   236 	    if (fires == DW_DLV_NO_ENTRY) {
       
   237 		continue;
       
   238 	    }
       
   239 	    if (row_pc != j) {
       
   240 		/* duplicate row */
       
   241 		break;
       
   242 	    }
       
   243 	    if (!printed_intro_addr) {
       
   244 		printf("    %08llx:\t", j);
       
   245 		printed_intro_addr = 1;
       
   246 	    }
       
   247 	    print_one_frame_reg_col(dbg,k,
       
   248 				    value_type,
       
   249 				    reg,
       
   250 				    config_data,
       
   251 				    offset_relevant, offset, block_ptr);
       
   252 
       
   253 	}
       
   254 	if (printed_intro_addr) {
       
   255 	    printf("\n");
       
   256 	    printed_intro_addr = 0;
       
   257 	}
       
   258     }
       
   259     if (verbose > 1) {
       
   260 	Dwarf_Off fde_off;
       
   261 	Dwarf_Off cie_off;
       
   262 
       
   263 	/* get the fde instructions and print them in raw form, just
       
   264 	   like cie instructions */
       
   265 	Dwarf_Ptr instrs;
       
   266 	Dwarf_Unsigned ilen;
       
   267 	int res;
       
   268 
       
   269 	res = dwarf_get_fde_instr_bytes(fde, &instrs, &ilen, &err);
       
   270 	offres =
       
   271 	    dwarf_fde_section_offset(dbg, fde, &fde_off, &cie_off,
       
   272 				      &err);
       
   273 	if (offres == DW_DLV_OK) {
       
   274 	    printf("\tfde sec. offset %llu 0x%llx"
       
   275 		   " cie offset for fde: %llu 0x%llx\n",
       
   276 		   (unsigned long long) fde_off,
       
   277 		   (unsigned long long) fde_off,
       
   278 		   (unsigned long long) cie_off,
       
   279 		   (unsigned long long) cie_off);
       
   280 
       
   281 	}
       
   282 
       
   283 
       
   284 	if (res == DW_DLV_OK) {
       
   285 	    int cires = 0;
       
   286 	    Dwarf_Unsigned cie_length = 0;
       
   287 	    Dwarf_Small version = 0;
       
   288 	    string augmenter;
       
   289 	    Dwarf_Unsigned code_alignment_factor = 0;
       
   290 	    Dwarf_Signed data_alignment_factor = 0;
       
   291 	    Dwarf_Half return_address_register_rule = 0;
       
   292 	    Dwarf_Ptr initial_instructions = 0;
       
   293 	    Dwarf_Unsigned initial_instructions_length = 0;
       
   294 
       
   295 	    if (cie_index >= cie_element_count) {
       
   296 		printf("Bad cie index %lld with fde index %lld! "
       
   297 		       "(table entry max %lld)\n",
       
   298 		       (long long) cie_index, (long long) fde_index,
       
   299 		       (long long) cie_element_count);
       
   300 		exit(1);
       
   301 	    }
       
   302 
       
   303 	    cires = dwarf_get_cie_info(cie_data[cie_index],
       
   304 				       &cie_length,
       
   305 				       &version,
       
   306 				       &augmenter,
       
   307 				       &code_alignment_factor,
       
   308 				       &data_alignment_factor,
       
   309 				       &return_address_register_rule,
       
   310 				       &initial_instructions,
       
   311 				       &initial_instructions_length,
       
   312 				       &err);
       
   313 	    if (cires == DW_DLV_ERROR) {
       
   314 		printf
       
   315 		    ("Bad cie index %lld with fde index %lld!\n",
       
   316 		     (long long) cie_index, (long long) fde_index);
       
   317 		print_error(dbg, "dwarf_get_cie_info", cires, err);
       
   318 	    }
       
   319 	    if (cires == DW_DLV_NO_ENTRY) {
       
   320 		;		/* ? */
       
   321 	    } else {
       
   322 
       
   323 		print_frame_inst_bytes(dbg, instrs,
       
   324 				       (Dwarf_Signed) ilen,
       
   325 				       data_alignment_factor,
       
   326 				       (int) code_alignment_factor,
       
   327 				       address_size, config_data);
       
   328 	    }
       
   329 	} else if (res == DW_DLV_NO_ENTRY) {
       
   330 	    printf
       
   331 		("Impossible: no instr bytes for fde index %d?\n",
       
   332 		 (int) fde_index);
       
   333 	} else {
       
   334 	    /* DW_DLV_ERROR */
       
   335 	    printf
       
   336 		("Error: on gettinginstr bytes for fde index %d?\n",
       
   337 		 (int) fde_index);
       
   338 	    print_error(dbg, "dwarf_get_fde_instr_bytes", res, err);
       
   339 	}
       
   340 
       
   341     }
       
   342     return DW_DLV_OK;
       
   343 }
       
   344 
       
   345 
       
   346 /* Print a cie.  Gather the print logic here so the
       
   347    control logic deciding what to print
       
   348    is clearer.
       
   349 */
       
   350 int
       
   351 print_one_cie(Dwarf_Debug dbg, Dwarf_Cie cie,
       
   352 	      Dwarf_Unsigned cie_index, Dwarf_Half address_size,
       
   353 	      struct dwconf_s *config_data)
       
   354 {
       
   355 
       
   356     int cires = 0;
       
   357     Dwarf_Unsigned cie_length = 0;
       
   358     Dwarf_Small version = 0;
       
   359     string augmenter = "";
       
   360     Dwarf_Unsigned code_alignment_factor = 0;
       
   361     Dwarf_Signed data_alignment_factor = 0;
       
   362     Dwarf_Half return_address_register_rule = 0;
       
   363     Dwarf_Ptr initial_instructions = 0;
       
   364     Dwarf_Unsigned initial_instructions_length = 0;
       
   365     Dwarf_Off cie_off = 0;
       
   366     Dwarf_Error err = 0;
       
   367 
       
   368     cires = dwarf_get_cie_info(cie,
       
   369 			       &cie_length,
       
   370 			       &version,
       
   371 			       &augmenter,
       
   372 			       &code_alignment_factor,
       
   373 			       &data_alignment_factor,
       
   374 			       &return_address_register_rule,
       
   375 			       &initial_instructions,
       
   376 			       &initial_instructions_length, &err);
       
   377     if (cires == DW_DLV_ERROR) {
       
   378 	print_error(dbg, "dwarf_get_cie_info", cires, err);
       
   379     }
       
   380     if (cires == DW_DLV_NO_ENTRY) {
       
   381 	;			/* ? */
       
   382 	printf("Impossible DW_DLV_NO_ENTRY on cie %d\n",
       
   383 	       (int) cie_index);
       
   384 	return DW_DLV_NO_ENTRY;
       
   385     }
       
   386     {
       
   387 	printf("<%3lld>\tversion\t\t\t\t%d\n", cie_index, version);
       
   388 	cires = dwarf_cie_section_offset(dbg, cie, &cie_off, &err);
       
   389 	if (cires == DW_DLV_OK) {
       
   390 	    printf("\tcie sec. offset %llu 0x%llx\n",
       
   391 		   (unsigned long long) cie_off,
       
   392 		   (unsigned long long) cie_off);
       
   393 
       
   394 	}
       
   395 
       
   396 	printf("\taugmentation\t\t\t%s\n", augmenter);
       
   397 	printf("\tcode_alignment_factor\t\t%llu\n",
       
   398 	       (unsigned long long) code_alignment_factor);
       
   399 	printf("\tdata_alignment_factor\t\t%lld\n",
       
   400 	       (long long) data_alignment_factor);
       
   401 	printf("\treturn_address_register\t\t%d\n",
       
   402 	       (int) return_address_register_rule);
       
   403 	{
       
   404 	    int ares = 0;
       
   405 	    Dwarf_Small *data = 0;
       
   406 	    Dwarf_Unsigned len = 0;
       
   407 
       
   408 	    ares =
       
   409 		dwarf_get_cie_augmentation_data(cie, &data, &len, &err);
       
   410 	    if (ares == DW_DLV_NO_ENTRY) {
       
   411 		/* do nothing. */
       
   412 	    } else if (ares == DW_DLV_OK && len > 0) {
       
   413 		int k2;
       
   414 
       
   415 		printf("\teh aug data len 0x%llx", (long long) len);
       
   416 		for (k2 = 0; data && k2 < len; ++k2) {
       
   417 		    if (k2 == 0) {
       
   418 			printf(" bytes 0x");
       
   419 		    }
       
   420 		    printf("%02x ", (unsigned char) data[k2]);
       
   421 		}
       
   422 		printf("\n");
       
   423 	    }			/* else DW_DLV_ERROR or no data, do
       
   424 				   nothing */
       
   425 	}
       
   426 
       
   427 	printf
       
   428 	    ("\tbytes of initial instructions:\t%lld\n",
       
   429 	     (long long) initial_instructions_length);
       
   430 	printf("\tcie length :\t\t\t%lld\n", (long long) cie_length);
       
   431 	print_frame_inst_bytes(dbg, initial_instructions, (Dwarf_Signed)
       
   432 			       initial_instructions_length,
       
   433 			       data_alignment_factor,
       
   434 			       (int) code_alignment_factor,
       
   435 			       address_size, config_data);
       
   436     }
       
   437     return DW_DLV_OK;
       
   438 }
       
   439 
       
   440 void
       
   441 get_string_from_locs(Dwarf_Debug dbg,
       
   442     Dwarf_Ptr bytes_in, 
       
   443     Dwarf_Unsigned block_len,struct esb_s *out_string)
       
   444 {
       
   445 
       
   446     Dwarf_Locdesc *locdescarray = 0;
       
   447     Dwarf_Signed listlen = 0;
       
   448     Dwarf_Error err2 =0;
       
   449     int skip_locdesc_header=1;
       
   450     int res2 = dwarf_loclist_from_expr(dbg,
       
   451         bytes_in,block_len,
       
   452         &locdescarray,
       
   453         &listlen,&err2);
       
   454     if (res2 == DW_DLV_ERROR) {
       
   455         print_error(dbg, "dwarf_get_loclist_from_expr",
       
   456             res2, err2);
       
   457     }
       
   458     if(res2==DW_DLV_NO_ENTRY) {
       
   459         return;
       
   460     }
       
   461     /* lcnt is always 1 */
       
   462 
       
   463     /* Use locdescarray  here.*/
       
   464     int res = dwarfdump_print_one_locdesc(dbg,
       
   465                          locdescarray,
       
   466                          skip_locdesc_header,
       
   467                          out_string);
       
   468     if(res != DW_DLV_OK) {
       
   469 	   printf("Bad status from _dwarf_print_one_locdesc %d\n",res);
       
   470            exit(1);
       
   471     }
       
   472             
       
   473 
       
   474     
       
   475     dwarf_dealloc(dbg, locdescarray->ld_s, DW_DLA_LOC_BLOCK);
       
   476     dwarf_dealloc(dbg, locdescarray, DW_DLA_LOCDESC);
       
   477         
       
   478 
       
   479     return ;
       
   480 }
       
   481 
       
   482 /* Print the frame instructions in detail for a glob of instructions.
       
   483 */
       
   484 
       
   485  /*ARGSUSED*/ void
       
   486 print_frame_inst_bytes(Dwarf_Debug dbg,
       
   487 		       Dwarf_Ptr cie_init_inst, Dwarf_Signed len,
       
   488 		       Dwarf_Signed data_alignment_factor,
       
   489 		       int code_alignment_factor, Dwarf_Half addr_size,
       
   490 		       struct dwconf_s *config_data)
       
   491 {
       
   492     unsigned char *instp = (unsigned char *) cie_init_inst;
       
   493     Dwarf_Unsigned uval;
       
   494     Dwarf_Unsigned uval2;
       
   495     unsigned int uleblen;
       
   496     unsigned int off = 0;
       
   497     unsigned int loff = 0;
       
   498     unsigned short u16;
       
   499     unsigned int u32;
       
   500     unsigned long long u64;
       
   501 
       
   502     for (; len > 0;) {
       
   503 	unsigned char ibyte = *instp;
       
   504 	int top = ibyte & 0xc0;
       
   505 	int bottom = ibyte & 0x3f;
       
   506 	int delta;
       
   507 	int reg;
       
   508 
       
   509 	switch (top) {
       
   510 	case DW_CFA_advance_loc:
       
   511 	    delta = ibyte & 0x3f;
       
   512 	    printf("\t%2u DW_CFA_advance_loc %d", off,
       
   513 		   (int) (delta * code_alignment_factor));
       
   514 	    if (verbose) {
       
   515 		printf("  (%d * %d)", (int) delta,
       
   516 		       (int) code_alignment_factor);
       
   517 	    }
       
   518 	    printf("\n");
       
   519 	    break;
       
   520 	case DW_CFA_offset:
       
   521 	    loff = off;
       
   522 	    reg = ibyte & 0x3f;
       
   523 	    uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
       
   524 	    instp += uleblen;
       
   525 	    len -= uleblen;
       
   526 	    off += uleblen;
       
   527 	    printf("\t%2u DW_CFA_offset ", loff);
       
   528 	    printreg((Dwarf_Signed) reg, config_data);
       
   529 	    printf(" %lld", (signed long long)
       
   530 		   (((Dwarf_Signed) uval) * data_alignment_factor));
       
   531 	    if (verbose) {
       
   532 		printf("  (%llu * %d)", (unsigned long long) uval,
       
   533 		       (int) data_alignment_factor);
       
   534 	    }
       
   535 	    printf("\n");
       
   536 	    break;
       
   537 
       
   538 	case DW_CFA_restore:
       
   539 	    reg = ibyte & 0x3f;
       
   540 	    printf("\t%2u DW_CFA_restore \n", off);
       
   541 	    printreg((Dwarf_Signed) reg, config_data);
       
   542 	    printf("\n");
       
   543 	    break;
       
   544 
       
   545 	default:
       
   546 	    loff = off;
       
   547 	    switch (bottom) {
       
   548 	    case DW_CFA_set_loc:
       
   549 		/* operand is address, so need address size */
       
   550 		/* which will be 4 or 8. */
       
   551 		switch (addr_size) {
       
   552 		case 4:
       
   553 		    {
       
   554 			__uint32_t v32;
       
   555 
       
   556 			memcpy(&v32, instp + 1, addr_size);
       
   557 			uval = v32;
       
   558 		    }
       
   559 		    break;
       
   560 		case 8:
       
   561 		    {
       
   562 			__uint64_t v64;
       
   563 
       
   564 			memcpy(&v64, instp + 1, addr_size);
       
   565 			uval = v64;
       
   566 		    }
       
   567 		    break;
       
   568 		default:
       
   569 		    printf
       
   570 			("Error: Unexpected address size %d in DW_CFA_set_loc!\n",
       
   571 			 addr_size);
       
   572 		    uval = 0;
       
   573 		}
       
   574 
       
   575 		instp += addr_size;
       
   576 		len -= (Dwarf_Signed) addr_size;
       
   577 		off += addr_size;
       
   578 		printf("\t%2u DW_CFA_set_loc %llu\n",
       
   579 		       loff, (unsigned long long) uval);
       
   580 		break;
       
   581 	    case DW_CFA_advance_loc1:
       
   582 		delta = (unsigned char) *(instp + 1);
       
   583 		uval2 = delta;
       
   584 		instp += 1;
       
   585 		len -= 1;
       
   586 		off += 1;
       
   587 		printf("\t%2u DW_CFA_advance_loc1 %llu\n",
       
   588 		       loff, (unsigned long long) uval2);
       
   589 		break;
       
   590 	    case DW_CFA_advance_loc2:
       
   591 		memcpy(&u16, instp + 1, 2);
       
   592 		uval2 = u16;
       
   593 		instp += 2;
       
   594 		len -= 2;
       
   595 		off += 2;
       
   596 		printf("\t%2u DW_CFA_advance_loc2 %llu\n",
       
   597 		       loff, (unsigned long long) uval2);
       
   598 		break;
       
   599 	    case DW_CFA_advance_loc4:
       
   600 		memcpy(&u32, instp + 1, 4);
       
   601 		uval2 = u32;
       
   602 		instp += 4;
       
   603 		len -= 4;
       
   604 		off += 4;
       
   605 		printf("\t%2u DW_CFA_advance_loc4 %llu\n",
       
   606 		       loff, (unsigned long long) uval2);
       
   607 		break;
       
   608 	    case DW_CFA_MIPS_advance_loc8:
       
   609 		memcpy(&u64, instp + 1, 8);
       
   610 		uval2 = u64;
       
   611 		instp += 8;
       
   612 		len -= 8;
       
   613 		off += 8;
       
   614 		printf("\t%2u DW_CFA_MIPS_advance_loc8 %llu\n",
       
   615 		       loff, (unsigned long long) uval2);
       
   616 		break;
       
   617 	    case DW_CFA_offset_extended:
       
   618 		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
       
   619 		instp += uleblen;
       
   620 		len -= uleblen;
       
   621 		off += uleblen;
       
   622 		uval2 =
       
   623 		    local_dwarf_decode_u_leb128(instp + 1, &uleblen);
       
   624 		instp += uleblen;
       
   625 		len -= uleblen;
       
   626 		off += uleblen;
       
   627 		printf("\t%2u DW_CFA_offset_extended ", loff);
       
   628 		printreg((Dwarf_Signed) uval, config_data);
       
   629 		printf(" %lld", (signed long long)
       
   630 		       (((Dwarf_Signed) uval2) *
       
   631 			data_alignment_factor));
       
   632 		if (verbose) {
       
   633 		    printf("  (%llu * %d)", (unsigned long long) uval2,
       
   634 			   (int) data_alignment_factor);
       
   635 		}
       
   636 		printf("\n");
       
   637 		break;
       
   638 
       
   639 	    case DW_CFA_restore_extended:
       
   640 		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
       
   641 		instp += uleblen;
       
   642 		len -= uleblen;
       
   643 		off += uleblen;
       
   644 		printf("\t%2u DW_CFA_restore_extended ", loff);
       
   645 		printreg((Dwarf_Signed) uval, config_data);
       
   646 		printf("\n");
       
   647 		break;
       
   648 	    case DW_CFA_undefined:
       
   649 		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
       
   650 		instp += uleblen;
       
   651 		len -= uleblen;
       
   652 		off += uleblen;
       
   653 		printf("\t%2u DW_CFA_undefined ", loff);
       
   654 		printreg((Dwarf_Signed) uval, config_data);
       
   655 		printf("\n");
       
   656 		break;
       
   657 	    case DW_CFA_same_value:
       
   658 		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
       
   659 		instp += uleblen;
       
   660 		len -= uleblen;
       
   661 		off += uleblen;
       
   662 		printf("\t%2u DW_CFA_same_value ", loff);
       
   663 		printreg((Dwarf_Signed) uval, config_data);
       
   664 		printf("\n");
       
   665 		break;
       
   666 	    case DW_CFA_register:
       
   667 		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
       
   668 		instp += uleblen;
       
   669 		len -= uleblen;
       
   670 		off += uleblen;
       
   671 		uval2 =
       
   672 		    local_dwarf_decode_u_leb128(instp + 1, &uleblen);
       
   673 		instp += uleblen;
       
   674 		len -= uleblen;
       
   675 		off += uleblen;
       
   676 		printf("\t%2u DW_CFA_register ", loff);
       
   677 		printreg((Dwarf_Signed) uval, config_data);
       
   678 		printf(" = ");
       
   679 		printreg((Dwarf_Signed) uval2, config_data);
       
   680 		printf("\n");
       
   681 		break;
       
   682 	    case DW_CFA_remember_state:
       
   683 		printf("\t%2u DW_CFA_remember_state\n", loff);
       
   684 		break;
       
   685 	    case DW_CFA_restore_state:
       
   686 		printf("\t%2u DW_CFA_restore_state\n", loff);
       
   687 		break;
       
   688 	    case DW_CFA_def_cfa:
       
   689 		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
       
   690 		instp += uleblen;
       
   691 		len -= uleblen;
       
   692 		off += uleblen;
       
   693 		uval2 =
       
   694 		    local_dwarf_decode_u_leb128(instp + 1, &uleblen);
       
   695 		instp += uleblen;
       
   696 		len -= uleblen;
       
   697 		off += uleblen;
       
   698 		printf("\t%2u DW_CFA_def_cfa ", loff);
       
   699 		printreg((Dwarf_Signed) uval, config_data);
       
   700 		printf(" %llu", (unsigned long long) uval2);
       
   701 		printf("\n");
       
   702 		break;
       
   703 	    case DW_CFA_def_cfa_register:
       
   704 		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
       
   705 		instp += uleblen;
       
   706 		len -= uleblen;
       
   707 		off += uleblen;
       
   708 		printf("\t%2u DW_CFA_def_cfa_register ", loff);
       
   709 		printreg((Dwarf_Signed) uval, config_data);
       
   710 		printf("\n");
       
   711 		break;
       
   712 	    case DW_CFA_def_cfa_offset:
       
   713 		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
       
   714 		instp += uleblen;
       
   715 		len -= uleblen;
       
   716 		off += uleblen;
       
   717 		printf("\t%2u DW_CFA_def_cfa_offset %llu\n",
       
   718 		       loff, (unsigned long long) uval);
       
   719 		break;
       
   720 
       
   721 	    case DW_CFA_nop:
       
   722 		printf("\t%2u DW_CFA_nop\n", loff);
       
   723 		break;
       
   724 
       
   725 	    case DW_CFA_def_cfa_expression:	/* DWARF3 */
       
   726 		{
       
   727 		    Dwarf_Unsigned block_len =
       
   728 			local_dwarf_decode_u_leb128(instp + 1,
       
   729 						    &uleblen);
       
   730 
       
   731 		    instp += uleblen;
       
   732 		    len -= uleblen;
       
   733 		    off += uleblen;
       
   734 		    printf
       
   735 			("\t%2u DW_CFA_def_cfa_expression expr block len %lld\n",
       
   736 			 loff, (unsigned long long)
       
   737 			 block_len);
       
   738 		    dump_block("\t\t", (char *) instp+1,
       
   739 			       (Dwarf_Signed) block_len);
       
   740                     printf("\n");
       
   741                     if(verbose) {
       
   742                       struct esb_s exprstring;
       
   743                       esb_constructor(&exprstring);
       
   744                       get_string_from_locs(dbg,
       
   745 			    instp+1,block_len,&exprstring);
       
   746                       printf("\t\t%s\n",esb_get_string(&exprstring));
       
   747                       esb_destructor(&exprstring);
       
   748                     }
       
   749 		    instp += block_len;
       
   750 		    len -= block_len;
       
   751 		    off += block_len;
       
   752 		}
       
   753 		break;
       
   754 	    case DW_CFA_expression:	/* DWARF3 */
       
   755 		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
       
   756 		instp += uleblen;
       
   757 		len -= uleblen;
       
   758 		off += uleblen;
       
   759 		{
       
   760                     /* instp is always 1 byte back, so we need +1
       
   761 			when we use it. See the final increment
       
   762                         of this for loop. */
       
   763 		    Dwarf_Unsigned block_len =
       
   764 			local_dwarf_decode_u_leb128(instp + 1,
       
   765 						    &uleblen);
       
   766 
       
   767 		    instp += uleblen;
       
   768 		    len -= uleblen;
       
   769 		    off += uleblen;
       
   770 		    printf
       
   771 			("\t%2u DW_CFA_expression %llu expr block len %lld\n",
       
   772 			 loff, (unsigned long long) uval,
       
   773 			 (unsigned long long)
       
   774 			 block_len);
       
   775 		    dump_block("\t\t", (char *) instp+1,
       
   776 			       (Dwarf_Signed) block_len);
       
   777                     printf("\n");
       
   778                     if(verbose) {
       
   779                       struct esb_s exprstring;
       
   780                       esb_constructor(&exprstring);
       
   781                       get_string_from_locs(dbg,
       
   782 			    instp+1,block_len,&exprstring);
       
   783                       printf("\t\t%s\n",esb_get_string(&exprstring));
       
   784                       esb_destructor(&exprstring);
       
   785                     }
       
   786 		    instp += block_len;
       
   787 		    len -= block_len;
       
   788 		    off += block_len;
       
   789 		}
       
   790 
       
   791 		break;
       
   792 	    case DW_CFA_cfa_offset_extended_sf:	/* DWARF3 */
       
   793 		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
       
   794 		instp += uleblen;
       
   795 		len -= uleblen;
       
   796 		off += uleblen;
       
   797 		{
       
   798                     /* instp is always 1 byte back, so we need +1
       
   799 			when we use it. See the final increment
       
   800                         of this for loop. */
       
   801 		    Dwarf_Signed sval2 =
       
   802 			local_dwarf_decode_s_leb128(instp + 1,
       
   803 						    &uleblen);
       
   804 
       
   805 		    instp += uleblen;
       
   806 		    len -= uleblen;
       
   807 		    off += uleblen;
       
   808 		    printf("\t%2u DW_CFA_offset_extended_sf ", loff);
       
   809 		    printreg((Dwarf_Signed) uval, config_data);
       
   810 		    printf(" %lld", (signed long long)
       
   811 			   ((sval2) * data_alignment_factor));
       
   812 		    if (verbose) {
       
   813 			printf("  (%lld * %d)", (long long) sval2,
       
   814 			       (int) data_alignment_factor);
       
   815 		    }
       
   816 		}
       
   817 		printf("\n");
       
   818 		break;
       
   819 	    case DW_CFA_def_cfa_sf:	/* DWARF3 */
       
   820                     /* instp is always 1 byte back, so we need +1
       
   821 			when we use it. See the final increment
       
   822                         of this for loop. */
       
   823 		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
       
   824 		instp += uleblen;
       
   825 		len -= uleblen;
       
   826 		off += uleblen;
       
   827 		{
       
   828 		    Dwarf_Signed sval2 =
       
   829 			local_dwarf_decode_s_leb128(instp + 1,
       
   830 						    &uleblen);
       
   831 
       
   832 		    instp += uleblen;
       
   833 		    len -= uleblen;
       
   834 		    off += uleblen;
       
   835 		    printf("\t%2u DW_CFA_def_cfa_sf ", loff);
       
   836 		    printreg((Dwarf_Signed) uval, config_data);
       
   837 		    printf(" %lld", (long long) sval2); 
       
   838                     printf(" (*data alignment factor=>%lld)",
       
   839                      (long long)(sval2*data_alignment_factor));
       
   840 		}
       
   841 		printf("\n");
       
   842 		break;
       
   843 	    case DW_CFA_def_cfa_offset_sf:	/* DWARF3 */
       
   844 		{
       
   845                     /* instp is always 1 byte back, so we need +1
       
   846 			when we use it. See the final increment
       
   847                         of this for loop. */
       
   848 		    Dwarf_Signed sval =
       
   849 			local_dwarf_decode_s_leb128(instp + 1,
       
   850 						    &uleblen);
       
   851 
       
   852 		    instp += uleblen;
       
   853 		    len -= uleblen;
       
   854 		    off += uleblen;
       
   855 		    printf("\t%2u DW_CFA_def_cfa_offset_sf %lld (*data alignment factor=> %lld)\n",
       
   856 			   loff, (long long) sval,
       
   857                            (long long)(data_alignment_factor*sval));
       
   858 
       
   859 		}
       
   860 		break;
       
   861 	    case DW_CFA_val_offset:	/* DWARF3 */
       
   862                     /* instp is always 1 byte back, so we need +1
       
   863 			when we use it. See the final increment
       
   864                         of this for loop. */
       
   865 		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
       
   866 		instp += uleblen;
       
   867 		len -= uleblen;
       
   868 		off += uleblen;
       
   869 		{
       
   870 		    uval2 =
       
   871 			local_dwarf_decode_s_leb128(instp + 1,
       
   872 						    &uleblen);
       
   873 		    instp += uleblen;
       
   874 		    len -= uleblen;
       
   875 		    off += uleblen;
       
   876 		    printf("\t%2u DW_CFA_val_offset ", loff);
       
   877 		    printreg((Dwarf_Signed) uval, config_data);
       
   878 		    printf(" %lld", (unsigned long long)
       
   879 			   (((Dwarf_Signed) uval2) *
       
   880 			    data_alignment_factor));
       
   881 		    if (verbose) {
       
   882 			printf("  (%lld * %d)", (long long) uval2,
       
   883 			       (int) data_alignment_factor);
       
   884 		    }
       
   885 		}
       
   886 		printf("\n");
       
   887 
       
   888 		break;
       
   889 	    case DW_CFA_val_offset_sf:	/* DWARF3 */
       
   890                     /* instp is always 1 byte back, so we need +1
       
   891 			when we use it. See the final increment
       
   892                         of this for loop. */
       
   893 		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
       
   894 		instp += uleblen;
       
   895 		len -= uleblen;
       
   896 		off += uleblen;
       
   897 		{
       
   898 		    Dwarf_Signed sval2 =
       
   899 			local_dwarf_decode_s_leb128(instp + 1,
       
   900 						    &uleblen);
       
   901 
       
   902 		    instp += uleblen;
       
   903 		    len -= uleblen;
       
   904 		    off += uleblen;
       
   905 		    printf("\t%2u DW_CFA_val_offset_sf ", loff);
       
   906 		    printreg((Dwarf_Signed) uval, config_data);
       
   907 		    printf(" %lld", (signed long long)
       
   908 			   ((sval2) * data_alignment_factor));
       
   909 		    if (verbose) {
       
   910 			printf("  (%lld * %d)", (long long) sval2,
       
   911 			       (int) data_alignment_factor);
       
   912 		    }
       
   913 		}
       
   914 		printf("\n");
       
   915 
       
   916 		break;
       
   917 	    case DW_CFA_val_expression:	/* DWARF3 */
       
   918                     /* instp is always 1 byte back, so we need +1
       
   919 			when we use it. See the final increment
       
   920                         of this for loop. */
       
   921 		uval = local_dwarf_decode_u_leb128(instp + 1, &uleblen);
       
   922 		instp += uleblen;
       
   923 		len -= uleblen;
       
   924 		off += uleblen;
       
   925 		{
       
   926 		    Dwarf_Unsigned block_len =
       
   927 			local_dwarf_decode_u_leb128(instp + 1,
       
   928 						    &uleblen);
       
   929 
       
   930 		    instp += uleblen;
       
   931 		    len -= uleblen;
       
   932 		    off += uleblen;
       
   933 		    printf
       
   934 			("\t%2u DW_CFA_val_expression %llu expr block len %lld\n",
       
   935 			 loff, (unsigned long long) uval,
       
   936 			 (unsigned long long)
       
   937 			 block_len);
       
   938 		    dump_block("\t\t", (char *) instp+1,
       
   939 			       (Dwarf_Signed) block_len);
       
   940                     printf("\n");
       
   941                     if(verbose) {
       
   942                       struct esb_s exprstring;
       
   943                       esb_constructor(&exprstring);
       
   944                       get_string_from_locs(dbg,
       
   945 			    instp+1,block_len,&exprstring);
       
   946                       printf("\t\t%s\n",esb_get_string(&exprstring));
       
   947                       esb_destructor(&exprstring);
       
   948                     }
       
   949 		    instp += block_len;
       
   950 		    len -= block_len;
       
   951 		    off += block_len;
       
   952 		}
       
   953 
       
   954 
       
   955 		break;
       
   956 
       
   957 
       
   958 #ifdef DW_CFA_GNU_window_save
       
   959 	    case DW_CFA_GNU_window_save:{
       
   960 		    /* no information: this just tells unwinder to
       
   961 		       restore the window registers from the previous
       
   962 		       frame's window save area */
       
   963 		    printf("\t%2u DW_CFA_GNU_window_save \n", loff);
       
   964 		    break;
       
   965 		}
       
   966 #endif
       
   967 #ifdef DW_CFA_GNU_negative_offset_extended
       
   968 	    case DW_CFA_GNU_negative_offset_extended:{
       
   969 		    printf
       
   970 			("\t%2u DW_CFA_GNU_negative_offset_extended \n",
       
   971 			 loff);
       
   972 		}
       
   973 #endif
       
   974 #ifdef  DW_CFA_GNU_args_size
       
   975 		/* single uleb128 is the current arg area size in
       
   976 		   bytes. no register exists yet to save this in */
       
   977 	    case DW_CFA_GNU_args_size:{
       
   978 		    Dwarf_Unsigned lreg;
       
   979 
       
   980                     /* instp is always 1 byte back, so we need +1
       
   981 			when we use it. See the final increment
       
   982                         of this for loop. */
       
   983 		    lreg =
       
   984 			local_dwarf_decode_u_leb128(instp + 1,
       
   985 						    &uleblen);
       
   986 		    printf
       
   987 			("\t%2u DW_CFA_GNU_args_size arg size: %llu\n",
       
   988 			 loff, (unsigned long long) lreg);
       
   989 		    instp += uleblen;
       
   990 		    len -= uleblen;
       
   991 		    off += uleblen;
       
   992 
       
   993 		    break;
       
   994 		}
       
   995 #endif
       
   996 
       
   997 	    default:
       
   998 		printf("\t%u Unexpected op 0x%x: \n",
       
   999 		       loff, (unsigned int) bottom);
       
  1000 		len = 0;
       
  1001 		break;
       
  1002 	    }
       
  1003 	}
       
  1004 	instp++;
       
  1005 	len--;
       
  1006 	off++;
       
  1007     }
       
  1008 }
       
  1009 
       
  1010 /* Print our register names for the cases we have a name.
       
  1011    Delegate to the configure code to actually do the print.
       
  1012 */
       
  1013 void
       
  1014 printreg(Dwarf_Signed reg, struct dwconf_s *config_data)
       
  1015 {
       
  1016     print_reg_from_config_data(reg, config_data);
       
  1017 }
       
  1018 
       
  1019 
       
  1020 /*
       
  1021    Actually does the printing of a rule in the table.
       
  1022    This may print something or may print nothing!
       
  1023 */
       
  1024 
       
  1025 static void
       
  1026 print_one_frame_reg_col(Dwarf_Debug dbg,
       
  1027                         Dwarf_Unsigned rule_id,
       
  1028                         Dwarf_Small value_type,
       
  1029                         Dwarf_Unsigned reg_used,
       
  1030                         struct dwconf_s *config_data,
       
  1031                         Dwarf_Signed offset_relevant,
       
  1032                         Dwarf_Signed offset, 
       
  1033                         Dwarf_Ptr block_ptr)
       
  1034 {
       
  1035     char *type_title = "";
       
  1036     int print_type_title = 1;
       
  1037 
       
  1038     if (config_data->cf_interface_number == 2)
       
  1039 	print_type_title = 0;
       
  1040 
       
  1041     switch (value_type) {
       
  1042     case DW_EXPR_OFFSET:
       
  1043 	type_title = "off";
       
  1044 	goto preg2;
       
  1045     case DW_EXPR_VAL_OFFSET:
       
  1046 	type_title = "valoff";
       
  1047       preg2:
       
  1048 	if (reg_used == config_data->cf_initial_rule_value) {
       
  1049 	    break;
       
  1050 	}
       
  1051 	if (print_type_title)
       
  1052 	    printf("<%s ", type_title);
       
  1053 	printreg((Dwarf_Signed) rule_id, config_data);
       
  1054 	printf("=");
       
  1055 	if (offset_relevant == 0) {
       
  1056 	    printreg((Dwarf_Signed) reg_used, config_data);
       
  1057 	    printf(" ");
       
  1058 	} else {
       
  1059 	    printf("%02lld", offset);
       
  1060 	    printf("(");
       
  1061 	    printreg((Dwarf_Signed) reg_used, config_data);
       
  1062 	    printf(") ");
       
  1063 	}
       
  1064 	if (print_type_title)
       
  1065 	    printf("%s", "> ");
       
  1066 	break;
       
  1067     case DW_EXPR_EXPRESSION:
       
  1068 	type_title = "expr";
       
  1069 	goto pexp2;
       
  1070     case DW_EXPR_VAL_EXPRESSION:
       
  1071 	type_title = "valexpr";
       
  1072       pexp2:
       
  1073 	if (print_type_title)
       
  1074 	    printf("<%s ", type_title);
       
  1075 	printreg((Dwarf_Signed) rule_id, config_data);
       
  1076 	printf("=");
       
  1077 	printf("expr-block-len=%lld", (long long) offset);
       
  1078 	if (print_type_title)
       
  1079 	    printf("%s", "> ");
       
  1080 	if (verbose) {
       
  1081 	    char pref[40];
       
  1082 
       
  1083 	    strcpy(pref, "<");
       
  1084 	    strcat(pref, type_title);
       
  1085 	    strcat(pref, "bytes:");
       
  1086 	    dump_block(pref, block_ptr, offset);
       
  1087 	    printf("%s", "> ");
       
  1088             if(verbose) {
       
  1089                       struct esb_s exprstring;
       
  1090                       esb_constructor(&exprstring);
       
  1091                       get_string_from_locs(dbg,
       
  1092 			    block_ptr,offset,&exprstring);
       
  1093                       printf("<expr:%s>",esb_get_string(&exprstring));
       
  1094                       esb_destructor(&exprstring);
       
  1095             }
       
  1096 	}
       
  1097 	break;
       
  1098     default:
       
  1099 	printf("Internal error in libdwarf, value type %d\n",
       
  1100 	       value_type);
       
  1101 	exit(1);
       
  1102     }
       
  1103     return;
       
  1104 }