1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
|
// -*- C++ -*-
// Copyright (C) 2008-2014 Red Hat Inc.
//
// This file is part of systemtap, and is free software. You can
// redistribute it and/or modify it under the terms of the GNU General
// Public License (GPL); either version 2, or (at your option) any
// later version.
#ifndef DWARF_WRAPPERS_H
#define DWARF_WRAPPERS_H 1
#include "config.h"
extern "C" {
#include <elfutils/libdw.h>
#include <elfutils/version.h>
#include <dwarf.h>
}
#include <string>
#if ! _ELFUTILS_PREREQ(0, 148)
#define DW_AT_linkage_name 0x6e
#endif
#if ! _ELFUTILS_PREREQ(0, 153)
#define DW_TAG_GNU_call_site 0x4109
#define DW_AT_GNU_tail_call 0x2115
#endif
#if ! _ELFUTILS_PREREQ(0, 155)
#define DW_ATE_UTF 0x10
#endif
#define DWFL_ASSERT(desc, arg) \
dwfl_assert(desc, arg, __FILE__, __LINE__)
// NB: "rc == 0" means OK in this case
void dwfl_assert(const std::string& desc, int rc,
const std::string& file, int line);
// Throw error if pointer is NULL
inline void
dwfl_assert(const std::string& desc, const void* ptr,
const std::string& file, int line)
{
if (!ptr)
dwfl_assert(desc, -1, file, line);
}
// Throw error if condition is false
inline void
dwfl_assert(const std::string& desc, bool condition,
const std::string& file, int line)
{
if (!condition)
dwfl_assert(desc, -1, file, line);
}
#define DWARF_ASSERT(desc, arg) \
dwarf_assert(desc, arg, __FILE__, __LINE__)
// NB: "rc == 0" means OK in this case
void dwarf_assert(const std::string& desc, int rc,
const std::string& file, int line);
// Throw error if pointer is NULL
inline void
dwarf_assert(const std::string& desc, const void* ptr,
const std::string& file, int line)
{
if (!ptr)
dwarf_assert(desc, -1, file, line);
}
#define DWARF_LINENO(line) \
safe_dwarf_lineno(line, __FILE__, __LINE__)
inline int
safe_dwarf_lineno(const Dwarf_Line* line,
const std::string& errfile, int errline)
{
int lineno;
dwarf_assert("dwarf_lineno",
dwarf_lineno(const_cast<Dwarf_Line*>(line), &lineno),
errfile, errline);
return lineno;
}
#define DWARF_LINEADDR(line) \
safe_dwarf_lineaddr(line, __FILE__, __LINE__)
inline Dwarf_Addr
safe_dwarf_lineaddr(const Dwarf_Line* line,
const std::string& errfile, int errline)
{
Dwarf_Addr addr;
dwarf_assert("dwarf_lineaddr",
dwarf_lineaddr(const_cast<Dwarf_Line*>(line), &addr),
errfile, errline);
return addr;
}
#define DWARF_LINESRC(line) \
safe_dwarf_linesrc(line, NULL, NULL, __FILE__, __LINE__)
#define DWARF_LINESRC2(line, mtime) \
safe_dwarf_linesrc(line, mtime, NULL, __FILE__, __LINE__)
#define DWARF_LINESRC3(line, mtime, length) \
safe_dwarf_linesrc(line, mtime, length, __FILE__, __LINE__)
inline const char*
safe_dwarf_linesrc(const Dwarf_Line* line,
Dwarf_Word* mtime,
Dwarf_Word* length,
const std::string& errfile, int errline)
{
const char* linesrc =
dwarf_linesrc(const_cast<Dwarf_Line*>(line), mtime, length);
dwarf_assert("dwarf_linesrc", linesrc, errfile, errline);
return linesrc;
}
#define DWARF_LINEPROLOGUEEND(line) \
safe_dwarf_lineprologueend(line, __FILE__, __LINE__)
inline bool
safe_dwarf_lineprologueend(const Dwarf_Line* line,
const std::string& errfile, int errline)
{
bool flag;
dwarf_assert("is_prologue_end",
dwarf_lineprologueend(const_cast<Dwarf_Line*>(line), &flag),
errfile, errline);
return flag;
}
// Look up the DIE for a reference-form attribute name
inline Dwarf_Die *
dwarf_attr_die (Dwarf_Die *die, unsigned int attr, Dwarf_Die *result)
{
Dwarf_Attribute attr_mem;
if (dwarf_formref_die (dwarf_attr_integrate (die, attr, &attr_mem),
result) != NULL)
{
/* If we want a type make sure we get the actual DIE describing
the real type. */
if (attr == DW_AT_type)
{
Dwarf_Attribute sigm;
Dwarf_Attribute *sig = dwarf_attr (result, DW_AT_signature, &sigm);
if (sig != NULL)
result = dwarf_formref_die (sig, result);
/* A DW_AT_signature might point to a type_unit, then
the actual type DIE we want is the first child. */
if (result != NULL && dwarf_tag (result) == DW_TAG_type_unit)
DWFL_ASSERT("type_unit child", dwarf_child (result, result));
}
return result;
}
return NULL;
}
// Retrieve the linkage name of a die, either by the MIPS vendor extension or
// DWARF4's standardized attribute.
inline const char *
dwarf_linkage_name (Dwarf_Die *die)
{
Dwarf_Attribute attr_mem;
return dwarf_formstring
(dwarf_attr_integrate (die, DW_AT_MIPS_linkage_name, &attr_mem)
?: dwarf_attr_integrate (die, DW_AT_linkage_name, &attr_mem));
}
#if !_ELFUTILS_PREREQ(0, 143)
// Elfutils prior to 0.143 didn't use attr_integrate when looking up the
// decl_file or decl_line, so the attributes would sometimes be missed. For
// those old versions, we define custom implementations to do the integration.
const char *dwarf_decl_file_integrate (Dwarf_Die *die);
#define dwarf_decl_file dwarf_decl_file_integrate
int dwarf_decl_line_integrate (Dwarf_Die *die, int *linep)
__nonnull_attribute__ (2);
#define dwarf_decl_line dwarf_decl_line_integrate
#endif // !_ELFUTILS_PREREQ(0, 143)
// Resolve a C declaration for dwarf types
bool dwarf_type_decl(Dwarf_Die *type_die, const std::string& var_name, std::string& decl);
// Resolve a full name for dwarf types
bool dwarf_type_name(Dwarf_Die *type_die, std::string& type_name);
std::string dwarf_type_name(Dwarf_Die *type_die);
#endif
/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
|