move pst_call_site & pst_parameter to C language and separate them
This commit is contained in:
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* dwarf_call_site.cpp
|
||||
*
|
||||
* Created on: Feb 1, 2020
|
||||
* Author: nnosov
|
||||
*/
|
||||
|
||||
#include <dwarf.h>
|
||||
|
||||
#include "dwarf_call_site.h"
|
||||
#include "dwarf_utils.h"
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
// pst_call_site_param
|
||||
// -----------------------------------------------------------------------------------
|
||||
void param_set_location(pst_call_site_param* param, Dwarf_Op* expr, size_t exprlen)
|
||||
{
|
||||
param->location.setup(¶m->location, expr, exprlen);
|
||||
}
|
||||
|
||||
void pst_call_site_param_init(pst_call_site_param* param)
|
||||
{
|
||||
// methods
|
||||
param->set_location = param_set_location;
|
||||
|
||||
// fields
|
||||
param->param = NULL;
|
||||
param->name = NULL;
|
||||
param->value = 0;
|
||||
pst_dwarf_expr_init(¶m->location);
|
||||
param->allocated = false;
|
||||
}
|
||||
|
||||
pst_call_site_param* pst_call_site_param_new()
|
||||
{
|
||||
pst_call_site_param* param = (pst_call_site_param*)allocator.alloc(&allocator, sizeof(pst_call_site_param));
|
||||
if(param) {
|
||||
pst_call_site_param_init(param);
|
||||
param->allocated = true;
|
||||
}
|
||||
|
||||
return param;
|
||||
}
|
||||
|
||||
void pst_call_site_param_fini(pst_call_site_param* param)
|
||||
{
|
||||
if(param->name) {
|
||||
allocator.free(&allocator, param->name);
|
||||
param->name = NULL;
|
||||
}
|
||||
|
||||
if(param->allocated) {
|
||||
allocator.free(&allocator, param);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
// pst_call_site
|
||||
// -----------------------------------------------------------------------------------
|
||||
pst_call_site_param* site_add_param(pst_call_site* site)
|
||||
{
|
||||
pst_call_site_param* p = pst_call_site_param_new();
|
||||
pst_call_site_param_init(p);
|
||||
list_add_bottom(&site->params, &p->node);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void site_del_param(pst_call_site*, pst_call_site_param* p)
|
||||
{
|
||||
list_del(&p->node);
|
||||
pst_call_site_param_fini(p);
|
||||
}
|
||||
|
||||
pst_call_site_param* site_next_param(pst_call_site* site, pst_call_site_param* p)
|
||||
{
|
||||
list_node* n = (p == NULL) ? list_first(&site->params) : list_next(&p->node);
|
||||
pst_call_site_param* ret = NULL;
|
||||
if(n) {
|
||||
ret = list_entry(n, pst_call_site_param, node);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
pst_call_site_param* site_find_param(pst_call_site* site, pst_dwarf_expr* expr)
|
||||
{
|
||||
for(pst_call_site_param* param = site_next_param(site, NULL); param; param = site_next_param(site, param)) {
|
||||
if(param->location.is_equal(¶m->location, expr)) {
|
||||
return param;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool site_handle_dwarf(pst_call_site* site, Dwarf_Die* child)
|
||||
{
|
||||
Dwarf_Attribute attr_mem;
|
||||
Dwarf_Attribute* attr;
|
||||
|
||||
do {
|
||||
switch(dwarf_tag(child))
|
||||
{
|
||||
case DW_TAG_GNU_call_site_parameter: {
|
||||
Dwarf_Addr pc;
|
||||
unw_get_reg(site->ctx->curr_frame, UNW_REG_IP, &pc);
|
||||
|
||||
// expression represent where callee parameter will be stored
|
||||
pst_call_site_param* param = site->add_param(site);
|
||||
if(dwarf_hasattr(child, DW_AT_location)) {
|
||||
// handle location expression here
|
||||
// determine location of parameter in stack/heap or CPU registers
|
||||
attr = dwarf_attr(child, DW_AT_location, &attr_mem);
|
||||
if(!handle_location(site->ctx, attr, ¶m->location, pc, NULL)) {
|
||||
site->ctx->log(SEVERITY_ERROR, "Failed to calculate DW_AT_location expression: %s", site->ctx->buff);
|
||||
site->del_param(site, param);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// expression represents call parameter's value
|
||||
if(dwarf_hasattr(child, DW_AT_GNU_call_site_value)) {
|
||||
// handle value expression here
|
||||
attr = dwarf_attr(child, DW_AT_GNU_call_site_value, &attr_mem);
|
||||
pst_dwarf_expr loc;
|
||||
pst_dwarf_expr_init(&loc);
|
||||
if(handle_location(site->ctx, attr, &loc, pc, NULL)) {
|
||||
param->value = loc.value;
|
||||
site->ctx->log(SEVERITY_DEBUG, "\tDW_AT_GNU_call_site_value:\"%s\" ==> 0x%lX", site->ctx->buff, param->value);
|
||||
} else {
|
||||
site->ctx->log(SEVERITY_ERROR, "Failed to calculate DW_AT_location expression: %s", site->ctx->buff);
|
||||
site->del_param(site, param);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} while (dwarf_siblingof (child, child) == 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void pst_call_site_init(pst_call_site* site, pst_context* c, uint64_t tgt, const char* orn) {
|
||||
// methods
|
||||
|
||||
|
||||
// fields
|
||||
list_node_init(&site->node);
|
||||
|
||||
site->target = tgt;
|
||||
if(orn) {
|
||||
site->origin = strdup(orn);
|
||||
} else {
|
||||
site->origin = NULL;
|
||||
}
|
||||
site->die = NULL;
|
||||
list_head_init(&site->params);
|
||||
site->ctx = c;
|
||||
site->allocated = false;
|
||||
}
|
||||
|
||||
pst_call_site* pst_call_site_new(pst_context* c, uint64_t tgt, const char* orn)
|
||||
{
|
||||
pst_call_site* nc = (pst_call_site*)allocator.alloc(&allocator, sizeof(pst_call_site));
|
||||
if(nc) {
|
||||
pst_call_site_init(nc, c, tgt, orn);
|
||||
nc->allocated = true;
|
||||
}
|
||||
|
||||
return nc;
|
||||
}
|
||||
|
||||
void pst_call_site_fini(pst_call_site* site)
|
||||
{
|
||||
if(site->origin) {
|
||||
allocator.free(&allocator, site->origin);
|
||||
site->origin = NULL;
|
||||
}
|
||||
|
||||
if(site->allocated) {
|
||||
allocator.free(&allocator, site);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user