|
Packit |
cdaae3 |
/*
|
|
Packit |
cdaae3 |
Copyright (c) 2009-2015 David Anderson.
|
|
Packit |
cdaae3 |
All rights reserved.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
Redistribution and use in source and binary forms, with or without
|
|
Packit |
cdaae3 |
modification, are permitted provided that the following conditions are met:
|
|
Packit |
cdaae3 |
* Redistributions of source code must retain the above copyright
|
|
Packit |
cdaae3 |
notice, this list of conditions and the following disclaimer.
|
|
Packit |
cdaae3 |
* Redistributions in binary form must reproduce the above copyright
|
|
Packit |
cdaae3 |
notice, this list of conditions and the following disclaimer in the
|
|
Packit |
cdaae3 |
documentation and/or other materials provided with the distribution.
|
|
Packit |
cdaae3 |
* Neither the name of the example nor the
|
|
Packit |
cdaae3 |
names of its contributors may be used to endorse or promote products
|
|
Packit |
cdaae3 |
derived from this software without specific prior written permission.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
THIS SOFTWARE IS PROVIDED BY David Anderson ''AS IS'' AND ANY
|
|
Packit |
cdaae3 |
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
Packit |
cdaae3 |
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
Packit |
cdaae3 |
DISCLAIMED. IN NO EVENT SHALL David Anderson BE LIABLE FOR ANY
|
|
Packit |
cdaae3 |
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
Packit |
cdaae3 |
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
Packit |
cdaae3 |
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
Packit |
cdaae3 |
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
Packit |
cdaae3 |
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
Packit |
cdaae3 |
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
*/
|
|
Packit |
cdaae3 |
/* simplereader.c
|
|
Packit |
cdaae3 |
This is an example of code reading dwarf .debug_frame.
|
|
Packit |
cdaae3 |
It is kept as simple as possible to expose essential features.
|
|
Packit |
cdaae3 |
It does not do all possible error reporting or error handling.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
It specifically calls dwarf_expand_frame_instructions()
|
|
Packit |
cdaae3 |
to verify that works without crashing!
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
To use, try
|
|
Packit |
cdaae3 |
make
|
|
Packit |
cdaae3 |
./frame1 frame1
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
gcc/clang may produce .eh_frame without .debug_frame.
|
|
Packit |
cdaae3 |
To read .eh_frame call dwarf_get_fde_list_eh()
|
|
Packit |
cdaae3 |
below instead of dwarf_get_fde_list() .
|
|
Packit |
cdaae3 |
*/
|
|
Packit |
cdaae3 |
#include "config.h"
|
|
Packit |
cdaae3 |
#include <sys/types.h> /* For open() */
|
|
Packit |
cdaae3 |
#include <sys/stat.h> /* For open() */
|
|
Packit |
cdaae3 |
#include <fcntl.h> /* For open() */
|
|
Packit |
cdaae3 |
#include <stdlib.h> /* For exit() */
|
|
Packit |
cdaae3 |
#ifdef HAVE_UNISTD_H
|
|
Packit |
cdaae3 |
#include <unistd.h> /* For close() */
|
|
Packit |
cdaae3 |
#endif
|
|
Packit |
cdaae3 |
#include <string.h> /* For strcmp* */
|
|
Packit |
cdaae3 |
#include <stdio.h>
|
|
Packit |
cdaae3 |
#include <errno.h>
|
|
Packit |
cdaae3 |
#include "dwarf.h"
|
|
Packit |
cdaae3 |
#include "libdwarf.h"
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
static void read_frame_data(Dwarf_Debug dbg);
|
|
Packit |
cdaae3 |
static void print_fde_instrs(Dwarf_Debug dbg, Dwarf_Fde fde,
|
|
Packit |
cdaae3 |
Dwarf_Error *error);
|
|
Packit |
cdaae3 |
static void print_regtable(Dwarf_Regtable3 *tab3);
|
|
Packit |
cdaae3 |
static void
|
|
Packit |
cdaae3 |
print_cie_instrs(Dwarf_Cie cie,Dwarf_Error *error);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
#define UNDEF_VAL 2000
|
|
Packit |
cdaae3 |
#define SAME_VAL 2001
|
|
Packit |
cdaae3 |
#define CFA_VAL 2002
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
int
|
|
Packit |
cdaae3 |
main(int argc, char **argv)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
Dwarf_Debug dbg = 0;
|
|
Packit |
cdaae3 |
int fd = -1;
|
|
Packit |
cdaae3 |
const char *filepath = "<stdin>";
|
|
Packit |
cdaae3 |
int res = DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
Dwarf_Error error;
|
|
Packit |
cdaae3 |
Dwarf_Handler errhand = 0;
|
|
Packit |
cdaae3 |
Dwarf_Ptr errarg = 0;
|
|
Packit |
cdaae3 |
int regtabrulecount = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if(argc < 2) {
|
|
Packit |
cdaae3 |
fd = 0; /* stdin */
|
|
Packit |
cdaae3 |
} else {
|
|
Packit |
cdaae3 |
filepath = argv[1];
|
|
Packit |
cdaae3 |
fd = open(filepath,O_RDONLY);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if(fd < 0) {
|
|
Packit |
cdaae3 |
printf("Failure attempting to open %s\n",filepath);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
res = dwarf_init(fd,DW_DLC_READ,errhand,errarg, &dbg,&error);
|
|
Packit |
cdaae3 |
if(res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
printf("Giving up, dwarf_init failed, cannot do DWARF processing\n");
|
|
Packit |
cdaae3 |
exit(1);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
/* Do this setting after init before any real operations.
|
|
Packit |
cdaae3 |
These return the old values, but here we do not
|
|
Packit |
cdaae3 |
need to know the old values. The sizes and
|
|
Packit |
cdaae3 |
values here are higher than most ABIs and entirely
|
|
Packit |
cdaae3 |
arbitrary.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
The setting of initial_value to
|
|
Packit |
cdaae3 |
the same as undefined-value (the other possible choice being
|
|
Packit |
cdaae3 |
same-value) is arbitrary, different ABIs do differ, and
|
|
Packit |
cdaae3 |
you have to know which is right. */
|
|
Packit |
cdaae3 |
regtabrulecount=1999;
|
|
Packit |
cdaae3 |
dwarf_set_frame_undefined_value(dbg, UNDEF_VAL);
|
|
Packit |
cdaae3 |
dwarf_set_frame_rule_initial_value(dbg, UNDEF_VAL);
|
|
Packit |
cdaae3 |
dwarf_set_frame_same_value(dbg,SAME_VAL);
|
|
Packit |
cdaae3 |
dwarf_set_frame_cfa_value(dbg,CFA_VAL);
|
|
Packit |
cdaae3 |
dwarf_set_frame_rule_table_size(dbg,regtabrulecount);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
read_frame_data(dbg);
|
|
Packit |
cdaae3 |
res = dwarf_finish(dbg,&error);
|
|
Packit |
cdaae3 |
if(res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
printf("dwarf_finish failed!\n");
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
close(fd);
|
|
Packit |
cdaae3 |
return 0;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
static void
|
|
Packit |
cdaae3 |
read_frame_data(Dwarf_Debug dbg)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
Dwarf_Error error;
|
|
Packit |
cdaae3 |
Dwarf_Signed cie_element_count = 0;
|
|
Packit |
cdaae3 |
Dwarf_Signed fde_element_count = 0;
|
|
Packit |
cdaae3 |
Dwarf_Cie *cie_data = 0;
|
|
Packit |
cdaae3 |
Dwarf_Fde *fde_data = 0;
|
|
Packit |
cdaae3 |
int res = DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
Dwarf_Signed fdenum = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* If you wish to read .eh_frame data, use
|
|
Packit |
cdaae3 |
dwarf_get_fde_list_eh() instead. */
|
|
Packit |
cdaae3 |
res = dwarf_get_fde_list(dbg,&cie_data,&cie_element_count,
|
|
Packit |
cdaae3 |
&fde_data,&fde_element_count,&error);
|
|
Packit |
cdaae3 |
if(res == DW_DLV_NO_ENTRY) {
|
|
Packit |
cdaae3 |
printf("No .debug_frame data present\n");
|
|
Packit |
cdaae3 |
printf("Try dwarf_get_fde_list_eh() to read .eh_frame data\n");
|
|
Packit |
cdaae3 |
exit(0);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if( res == DW_DLV_ERROR) {
|
|
Packit |
cdaae3 |
printf("Error reading frame data ");
|
|
Packit |
cdaae3 |
exit(1);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
printf( "%" DW_PR_DSd " cies present. "
|
|
Packit |
cdaae3 |
"%" DW_PR_DSd " fdes present. \n",
|
|
Packit |
cdaae3 |
cie_element_count,fde_element_count);
|
|
Packit |
cdaae3 |
/*if(fdenum >= fde_element_count) {
|
|
Packit |
cdaae3 |
printf("Want fde %d but only %" DW_PR_DSd " present\n",fdenum,
|
|
Packit |
cdaae3 |
fde_element_count);
|
|
Packit |
cdaae3 |
exit(1);
|
|
Packit |
cdaae3 |
}*/
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
for(fdenum = 0; fdenum < fde_element_count; ++fdenum) {
|
|
Packit |
cdaae3 |
Dwarf_Cie cie = 0;
|
|
Packit |
cdaae3 |
printf("Print cie of fde %" DW_PR_DSd "\n",fdenum);
|
|
Packit |
cdaae3 |
res = dwarf_get_cie_of_fde(fde_data[fdenum],&cie,&error);
|
|
Packit |
cdaae3 |
if(res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
printf("Error accessing fdenum %" DW_PR_DSd
|
|
Packit |
cdaae3 |
" to get its cie\n",fdenum);
|
|
Packit |
cdaae3 |
exit(1);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
print_cie_instrs(cie,&error);
|
|
Packit |
cdaae3 |
printf("Print fde %" DW_PR_DSd "\n",fdenum);
|
|
Packit |
cdaae3 |
print_fde_instrs(dbg,fde_data[fdenum],&error);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Done with the data. */
|
|
Packit |
cdaae3 |
dwarf_fde_cie_list_dealloc(dbg,cie_data,cie_element_count,
|
|
Packit |
cdaae3 |
fde_data, fde_element_count);
|
|
Packit |
cdaae3 |
return;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
static void
|
|
Packit |
cdaae3 |
print_cie_instrs(Dwarf_Cie cie,Dwarf_Error *error)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
int res = DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned bytes_in_cie = 0;
|
|
Packit |
cdaae3 |
Dwarf_Small version = 0;
|
|
Packit |
cdaae3 |
char *augmentation = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned code_alignment_factor = 0;
|
|
Packit |
cdaae3 |
Dwarf_Signed data_alignment_factor = 0;
|
|
Packit |
cdaae3 |
Dwarf_Half return_address_register_rule = 0;
|
|
Packit |
cdaae3 |
Dwarf_Ptr instrp = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned instr_len = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
res = dwarf_get_cie_info(cie,&bytes_in_cie,
|
|
Packit |
cdaae3 |
&version, &augmentation, &code_alignment_factor,
|
|
Packit |
cdaae3 |
&data_alignment_factor, &return_address_register_rule,
|
|
Packit |
cdaae3 |
&instrp,&instr_len,error);
|
|
Packit |
cdaae3 |
if(res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
printf("Unable to get cie info!\n");
|
|
Packit |
cdaae3 |
exit(1);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
static void
|
|
Packit |
cdaae3 |
print_frame_instrs(Dwarf_Frame_Op *frame_op_list,
|
|
Packit |
cdaae3 |
Dwarf_Signed frame_op_count)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
Dwarf_Signed i = 0;
|
|
Packit |
cdaae3 |
printf("Base op. Ext op. Reg. Offset. Instr-offset.\n");
|
|
Packit |
cdaae3 |
for(i = 0; i < frame_op_count; ++i) {
|
|
Packit |
cdaae3 |
printf("[%" DW_PR_DSd "]", i);
|
|
Packit |
cdaae3 |
printf(" %d. ", frame_op_list[i].fp_base_op);
|
|
Packit |
cdaae3 |
printf(" %d. ", frame_op_list[i].fp_extended_op);
|
|
Packit |
cdaae3 |
printf(" %" DW_PR_DSd ". ", frame_op_list[i].fp_offset);
|
|
Packit |
cdaae3 |
printf(" 0x%" DW_PR_DUx ". ", frame_op_list[i].fp_instr_offset);
|
|
Packit |
cdaae3 |
printf("\n");
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
static void
|
|
Packit |
cdaae3 |
print_fde_instrs(Dwarf_Debug dbg,
|
|
Packit |
cdaae3 |
Dwarf_Fde fde, Dwarf_Error *error)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
int res;
|
|
Packit |
cdaae3 |
Dwarf_Addr lowpc = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned func_length = 0;
|
|
Packit |
cdaae3 |
Dwarf_Ptr fde_bytes;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned fde_byte_length = 0;
|
|
Packit |
cdaae3 |
Dwarf_Off cie_offset = 0;
|
|
Packit |
cdaae3 |
Dwarf_Signed cie_index = 0;
|
|
Packit |
cdaae3 |
Dwarf_Off fde_offset = 0;
|
|
Packit |
cdaae3 |
Dwarf_Addr arbitrary_addr = 0;
|
|
Packit |
cdaae3 |
Dwarf_Addr actual_pc = 0;
|
|
Packit |
cdaae3 |
Dwarf_Regtable3 tab3;
|
|
Packit |
cdaae3 |
int oldrulecount = 0;
|
|
Packit |
cdaae3 |
Dwarf_Ptr outinstrs = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned instrslen = 0;
|
|
Packit |
cdaae3 |
Dwarf_Frame_Op * frame_op_list = 0;
|
|
Packit |
cdaae3 |
Dwarf_Signed frame_op_count = 0;
|
|
Packit |
cdaae3 |
Dwarf_Cie cie = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
res = dwarf_get_fde_range(fde,&lowpc,&func_length,&fde_bytes,
|
|
Packit |
cdaae3 |
&fde_byte_length,&cie_offset,&cie_index,&fde_offset,error);
|
|
Packit |
cdaae3 |
if(res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
printf("Problem getting fde range \n");
|
|
Packit |
cdaae3 |
exit(1);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
arbitrary_addr = lowpc + (func_length/2);
|
|
Packit |
cdaae3 |
printf("function low pc 0x%" DW_PR_DUx
|
|
Packit |
cdaae3 |
" and length 0x%" DW_PR_DUx
|
|
Packit |
cdaae3 |
" and addr we choose 0x%" DW_PR_DUx
|
|
Packit |
cdaae3 |
"\n",
|
|
Packit |
cdaae3 |
lowpc,func_length,arbitrary_addr);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* 1 is arbitrary. We are winding up getting the
|
|
Packit |
cdaae3 |
rule count here while leaving things unchanged. */
|
|
Packit |
cdaae3 |
oldrulecount = dwarf_set_frame_rule_table_size(dbg,1);
|
|
Packit |
cdaae3 |
dwarf_set_frame_rule_table_size(dbg,oldrulecount);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
tab3.rt3_reg_table_size = oldrulecount;
|
|
Packit |
cdaae3 |
tab3.rt3_rules = (struct Dwarf_Regtable_Entry3_s *) malloc(
|
|
Packit |
cdaae3 |
sizeof(struct Dwarf_Regtable_Entry3_s)* oldrulecount);
|
|
Packit |
cdaae3 |
if (!tab3.rt3_rules) {
|
|
Packit |
cdaae3 |
printf("Unable to malloc for %d rules\n",oldrulecount);
|
|
Packit |
cdaae3 |
exit(1);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
res = dwarf_get_fde_info_for_all_regs3(fde,arbitrary_addr ,
|
|
Packit |
cdaae3 |
&tab3,&actual_pc,error);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if(res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
printf("dwarf_get_fde_info_for_all_regs3 failed!\n");
|
|
Packit |
cdaae3 |
exit(1);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
print_regtable(&tab3);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
res = dwarf_get_fde_instr_bytes(fde,&outinstrs,&instrslen,error);
|
|
Packit |
cdaae3 |
if(res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
printf("dwarf_get_fde_instr_bytes failed!\n");
|
|
Packit |
cdaae3 |
exit(1);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
res = dwarf_get_cie_of_fde(fde,&cie,error);
|
|
Packit |
cdaae3 |
if(res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
printf("Error getting cie from fde\n");
|
|
Packit |
cdaae3 |
exit(1);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
res = dwarf_expand_frame_instructions(cie,
|
|
Packit |
cdaae3 |
outinstrs,instrslen,&frame_op_list,
|
|
Packit |
cdaae3 |
&frame_op_count,error);
|
|
Packit |
cdaae3 |
if(res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
printf("dwarf_expand_frame_instructions failed!\n");
|
|
Packit |
cdaae3 |
exit(1);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
printf("Frame op count: %" DW_PR_DUu "\n",frame_op_count);
|
|
Packit |
cdaae3 |
print_frame_instrs(frame_op_list,frame_op_count);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
dwarf_dealloc(dbg,frame_op_list, DW_DLA_FRAME_BLOCK);
|
|
Packit |
cdaae3 |
free(tab3.rt3_rules);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
static void
|
|
Packit |
cdaae3 |
print_reg(int r)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
switch(r) {
|
|
Packit |
cdaae3 |
case SAME_VAL:
|
|
Packit |
cdaae3 |
printf(" %d SAME_VAL ",r);
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
case UNDEF_VAL:
|
|
Packit |
cdaae3 |
printf(" %d UNDEF_VAL ",r);
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
case CFA_VAL:
|
|
Packit |
cdaae3 |
printf(" %d (CFA) ",r);
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
default:
|
|
Packit |
cdaae3 |
printf(" r%d ",r);
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
static void
|
|
Packit |
cdaae3 |
print_one_regentry(const char *prefix,
|
|
Packit |
cdaae3 |
struct Dwarf_Regtable_Entry3_s *entry)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
int is_cfa = !strcmp("cfa",prefix);
|
|
Packit |
cdaae3 |
printf("%s ",prefix);
|
|
Packit |
cdaae3 |
printf("type: %d %s ",
|
|
Packit |
cdaae3 |
entry->dw_value_type,
|
|
Packit |
cdaae3 |
(entry->dw_value_type == DW_EXPR_OFFSET)? "DW_EXPR_OFFSET":
|
|
Packit |
cdaae3 |
(entry->dw_value_type == DW_EXPR_VAL_OFFSET)? "DW_EXPR_VAL_OFFSET":
|
|
Packit |
cdaae3 |
(entry->dw_value_type == DW_EXPR_EXPRESSION)? "DW_EXPR_EXPRESSION":
|
|
Packit |
cdaae3 |
(entry->dw_value_type == DW_EXPR_VAL_EXPRESSION)?
|
|
Packit |
cdaae3 |
"DW_EXPR_VAL_EXPRESSION":
|
|
Packit |
cdaae3 |
"Unknown");
|
|
Packit |
cdaae3 |
switch(entry->dw_value_type) {
|
|
Packit |
cdaae3 |
case DW_EXPR_OFFSET:
|
|
Packit |
cdaae3 |
print_reg(entry->dw_regnum);
|
|
Packit |
cdaae3 |
printf(" offset_rel? %d ",entry->dw_offset_relevant);
|
|
Packit |
cdaae3 |
if(entry->dw_offset_relevant) {
|
|
Packit |
cdaae3 |
printf(" offset %" DW_PR_DSd " " ,
|
|
Packit |
cdaae3 |
entry->dw_offset_or_block_len);
|
|
Packit |
cdaae3 |
if(is_cfa) {
|
|
Packit |
cdaae3 |
printf("defines cfa value");
|
|
Packit |
cdaae3 |
} else {
|
|
Packit |
cdaae3 |
printf("address of value is CFA plus signed offset");
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if(!is_cfa && entry->dw_regnum != CFA_VAL) {
|
|
Packit |
cdaae3 |
printf(" compiler botch, regnum != CFA_VAL");
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
} else {
|
|
Packit |
cdaae3 |
printf("value in register");
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
case DW_EXPR_VAL_OFFSET:
|
|
Packit |
cdaae3 |
print_reg(entry->dw_regnum);
|
|
Packit |
cdaae3 |
printf(" offset %" DW_PR_DSd " " ,
|
|
Packit |
cdaae3 |
entry->dw_offset_or_block_len);
|
|
Packit |
cdaae3 |
if(is_cfa) {
|
|
Packit |
cdaae3 |
printf("does this make sense? No?");
|
|
Packit |
cdaae3 |
} else {
|
|
Packit |
cdaae3 |
printf("value at CFA plus signed offset");
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if(!is_cfa && entry->dw_regnum != CFA_VAL) {
|
|
Packit |
cdaae3 |
printf(" compiler botch, regnum != CFA_VAL");
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
case DW_EXPR_EXPRESSION:
|
|
Packit |
cdaae3 |
print_reg(entry->dw_regnum);
|
|
Packit |
cdaae3 |
printf(" offset_rel? %d ",entry->dw_offset_relevant);
|
|
Packit |
cdaae3 |
printf(" offset %" DW_PR_DSd " " ,
|
|
Packit |
cdaae3 |
entry->dw_offset_or_block_len);
|
|
Packit |
cdaae3 |
printf("Block ptr set? %s ",entry->dw_block_ptr?"yes":"no");
|
|
Packit |
cdaae3 |
printf(" Value is at address given by expr val ");
|
|
Packit |
cdaae3 |
/* printf(" block-ptr 0x%" DW_PR_DUx " ",
|
|
Packit |
cdaae3 |
(Dwarf_Unsigned)entry->dw_block_ptr); */
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
case DW_EXPR_VAL_EXPRESSION:
|
|
Packit |
cdaae3 |
printf(" expression byte len %" DW_PR_DSd " " ,
|
|
Packit |
cdaae3 |
entry->dw_offset_or_block_len);
|
|
Packit |
cdaae3 |
printf("Block ptr set? %s ",entry->dw_block_ptr?"yes":"no");
|
|
Packit |
cdaae3 |
printf(" Value is expr val ");
|
|
Packit |
cdaae3 |
if(!entry->dw_block_ptr) {
|
|
Packit |
cdaae3 |
printf("Compiler botch. ");
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
/* printf(" block-ptr 0x%" DW_PR_DUx " ",
|
|
Packit |
cdaae3 |
(Dwarf_Unsigned)entry->dw_block_ptr); */
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
printf("\n");
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
static void
|
|
Packit |
cdaae3 |
print_regtable(Dwarf_Regtable3 *tab3)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
int r;
|
|
Packit |
cdaae3 |
/* We won't print too much. A bit arbitrary. */
|
|
Packit |
cdaae3 |
int max = 10;
|
|
Packit |
cdaae3 |
if(max > tab3->rt3_reg_table_size) {
|
|
Packit |
cdaae3 |
max = tab3->rt3_reg_table_size;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
print_one_regentry("cfa",&tab3->rt3_cfa_rule);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
for(r = 0; r < max; r++) {
|
|
Packit |
cdaae3 |
char rn[30];
|
|
Packit |
cdaae3 |
snprintf(rn,sizeof(rn),"reg %d",r);
|
|
Packit |
cdaae3 |
print_one_regentry(rn,tab3->rt3_rules+r);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|