mtrace/dwarf.h
2015-05-04 12:32:45 +02:00

140 lines
4.5 KiB
C

/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the libunwind source
*
* This work was sponsored by Rohde & Schwarz GmbH & Co. KG, Munich.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_DWARF_H
#define _INC_DWARF_H
#include <stdint.h>
#include "arch.h"
#include "forward.h"
#include "mtelf.h"
#define DWARF_LOC(r, t) ((struct dwarf_loc){ .val = (r), .type = (t) })
#define DWARF_GET_LOC(l) ((l).val)
#define DWARF_LOC_TYPE_MEM 0
#define DWARF_LOC_TYPE_REG 1
#define DWARF_LOC_TYPE_VAL 2
#define DWARF_NULL_LOC DWARF_LOC(0, 0)
#define DWARF_MEM_LOC(m) DWARF_LOC((m), DWARF_LOC_TYPE_MEM)
#define DWARF_REG_LOC(r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
#define DWARF_VAL_LOC(v) DWARF_LOC((v), DWARF_LOC_TYPE_VAL)
#define DWARF_IS_NULL_LOC(l) ({ struct dwarf_loc _l = (l); _l.val == 0 && _l.type == 0; })
#define DWARF_IS_MEM_LOC(l) ((l).type == DWARF_LOC_TYPE_MEM)
#define DWARF_IS_REG_LOC(l) ((l).type == DWARF_LOC_TYPE_REG)
#define DWARF_IS_VAL_LOC(l) ((l).type == DWARF_LOC_TYPE_VAL)
#define DWARF_ADDR_SIZE(as) ((as)->is_64bit ? 8 : 4)
#define DWARF_ENOMEM 1 /* out of memory */
#define DWARF_EBADREG 2 /* bad register number */
#define DWARF_EBADFRAME 3 /* bad frame */
#define DWARF_EINVAL 4 /* unsupported operation or bad value */
#define DWARF_EBADVERSION 5 /* unwind info has unsupported version */
#define DWARF_ENOINFO 6 /* no unwind info found */
#define DWARF_STOPUNWIND 7 /* no unwind info found */
struct dwarf_cie_info {
arch_addr_t start_ip; /* first IP covered by this procedure */
arch_addr_t ip_range; /* ip range covered by this procedure */
arch_addr_t cie_instr_start; /* start addr. of CIE "initial_instructions" */
arch_addr_t cie_instr_end; /* end addr. of CIE "initial_instructions" */
arch_addr_t fde_instr_start; /* start addr. of FDE "instructions" */
arch_addr_t fde_instr_end; /* end addr. of FDE "instructions" */
arch_addr_t code_align; /* code-alignment factor */
arch_addr_t data_align; /* data-alignment factor */
arch_addr_t ret_addr_column; /* column of return-address register */
uint16_t abi;
uint16_t tag;
uint8_t fde_encoding;
uint8_t lsda_encoding;
unsigned int sized_augmentation:1;
unsigned int have_abi_marker:1;
unsigned int signal_frame:1;
};
struct dwarf_loc {
unsigned long val;
unsigned int type;
};
struct dwarf_cursor {
struct task *task;
arch_addr_t cfa; /* canonical frame address; aka frame-/stack-pointer */
arch_addr_t ip; /* instruction pointer */
arch_addr_t ret_addr_column; /* column for return-address */
unsigned int use_prev_instr:1; /* use previous (= call) or current (= signal) instruction? */
unsigned int valid:1;
struct library *lib;
struct dwarf_cie_info dci;
struct dwarf_loc *loc;
};
struct dwarf_addr_space {
unsigned int is_64bit:1;
arch_addr_t addr;
union {
long val;
unsigned char val_bytes[sizeof(long)];
};
struct dwarf_cursor cursor;
unsigned int ip_reg;
unsigned int ret_reg;
unsigned int num_regs;
};
struct dwarf_eh_frame_hdr;
void *dwarf_init(int is_64bit);
void dwarf_destroy(struct dwarf_addr_space *as);
int dwarf_init_unwind(struct dwarf_addr_space *as, struct task *task);
int dwarf_step(struct dwarf_addr_space *as);
arch_addr_t dwarf_get_ip(struct dwarf_addr_space *as);
int dwarf_locate_map(struct dwarf_addr_space *as, arch_addr_t ip);
int dwarf_get(struct dwarf_addr_space *as, struct dwarf_loc loc, arch_addr_t *valp);
int dwarf_get_unwind_table(struct task *task, struct library *lib, struct dwarf_eh_frame_hdr *hdr);
int dwarf_arch_init(struct dwarf_addr_space *as);
int dwarf_arch_init_unwind(struct dwarf_addr_space *as);
int dwarf_arch_step(struct dwarf_addr_space *as);
int dwarf_arch_map_reg(struct dwarf_addr_space *as, unsigned int reg);
#ifdef DWARF_TO_REGNUM
unsigned int dwarf_to_regnum(unsigned int reg);
#else
static inline unsigned int dwarf_to_regnum(unsigned int reg)
{
return reg;
}
#endif
#endif