Skip to content

Commit

Permalink
Fixing DwarfFrameParser to seek FDE and not Dwarf_Frame.
Browse files Browse the repository at this point in the history
  • Loading branch information
Sasha Nicolas committed Aug 18, 2017
1 parent 00ffcb9 commit 7a63dae
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 54 deletions.
2 changes: 1 addition & 1 deletion dwarf/CMakeLists.txt
Expand Up @@ -20,7 +20,7 @@ set (SRC_LIST
)


dyninst_library(dynDwarf dynElf common ${LIBDWARF_LIBRARIES})
dyninst_library(dynDwarf dynElf common ${LIBDWARF_LIBRARIES} ${LIBELF_LIBRARIES})
if (USE_COTIRE)
cotire(dynDwarf)
endif()
15 changes: 6 additions & 9 deletions dwarf/h/dwarfFrameParser.h
Expand Up @@ -55,14 +55,6 @@ typedef enum {
FE_No_Error
} FrameErrors_t;

/*typedef struct {
Dwarf_FDE *fde_data;
Dwarf_Sword fde_count;
Dwarf_CIE *cie_data;
Dwarf_Sword cie_count;
} fde_cie_data;*/


class DYNDWARF_EXPORT DwarfFrameParser {
public:

Expand Down Expand Up @@ -162,7 +154,12 @@ class DYNDWARF_EXPORT DwarfFrameParser {

dwarf_status_t fde_dwarf_status;

std::vector<Dwarf_CFI *> cfi_data;
typedef struct {
std::vector<Dwarf_CFI_Entry> cfi_entries;
Dwarf_CFI * cfi;
}CFI_data;

std::vector<CFI_data> cfi_data;

};

Expand Down
131 changes: 87 additions & 44 deletions dwarf/src/dwarfFrameParser.C
Expand Up @@ -36,27 +36,14 @@
#include <stdio.h>
#include <iostream>
#include "debug_common.h" // dwarf_printf
#include <libelf.h>

//#define DW_FRAME_CFA_COL3 ((Dwarf_Half) -1)
#define DW_FRAME_CFA_COL3 1036
using namespace Dyninst;
using namespace DwarfDyninst;
using namespace std;

/*struct frameParser_key
{
Dwarf * dbg;
Architecture arch;
frameParser_key(Dwarf * d, Architecture a) : dbg(d), arch(a)
{
}
bool operator< (const frameParser_key& rhs) const
{
return (dbg < rhs.dbg) || (dbg == rhs.dbg && arch < rhs.arch);
}
};*/

std::map<DwarfFrameParser::frameParser_key, DwarfFrameParser::Ptr> DwarfFrameParser::frameParsers;

Expand Down Expand Up @@ -200,7 +187,7 @@ bool DwarfFrameParser::getRegsForFunction(

dwarf_printf("\t Got FDE range 0x%lx..0x%lx\n", low, high);

unique_ptr<Dwarf_Frame, decltype(std::free)*> frame_ptr(frame, &std::free);
//unique_ptr<Dwarf_Frame, decltype(std::free)*> frame_ptr(frame, &std::free);

Dwarf_Half dwarf_reg;
if (!getDwarfReg(reg, frame, dwarf_reg, err_result)) {
Expand Down Expand Up @@ -263,7 +250,7 @@ bool DwarfFrameParser::getRegAtFrame(Address pc,
return false;
}

unique_ptr<Dwarf_Frame, decltype(std::free)*> frame_ptr(frame, &std::free);
//unique_ptr<Dwarf_Frame, decltype(std::free)*> frame_ptr(frame, &std::free);

Dwarf_Half dwarf_reg;
if (!getDwarfReg(reg, frame, dwarf_reg, err_result)) {
Expand Down Expand Up @@ -383,6 +370,28 @@ bool DwarfFrameParser::getRegAtFrame_aux(Address pc,
return true;
}

int section_id(Elf * elf)
{
char *identp = elf_getident(elf, NULL);
bool is64 = (identp && identp[EI_CLASS] == ELFCLASS64);

auto shstrtab_idx = !is64 ? elf32_getehdr(elf)->e_shstrndx : elf64_getehdr(elf)->e_shstrndx;
Elf_Scn *scn= elf_getscn(elf, shstrtab_idx);
//void *shdr = !is64 ? (void *)elf32_getshdr(scn) : (void *)elf64_getshdr(scn);
Elf_Data *data = elf_getdata(scn, NULL);
const char *shnames = (const char *)data->d_buf;

unsigned short num_sections = !is64 ? elf32_getehdr(elf)->e_shnum : elf64_getehdr(elf)->e_shnum;
for (unsigned i = 0; i < num_sections; i++) {
Elf_Scn *scn = elf_getscn(elf, i);
unsigned long name_idx = !is64 ? elf32_getshdr(scn)->sh_name : elf64_getshdr(scn)->sh_name;
//if (shdr.sh_type() == SHT_NOBITS) continue;
if (strcmp(".eh_frame", shnames + name_idx) == 0) {
return i;
}
}
return -1;
}

void DwarfFrameParser::setupFdeData()
{
Expand All @@ -399,16 +408,41 @@ void DwarfFrameParser::setupFdeData()
dwarf_set_frame_cfa_value(dbg, DW_FRAME_CFA_COL3);
#endif

// Try to get dwarf data from .debug_frame
Dwarf_CFI * cfi = dwarf_getcfi(dbg);
if (cfi) {
cfi_data.push_back(cfi);
//cfi_data.push_back(cfi);
}

// Try to get dwarf data from .eh_frame
Elf * elf = dwarf_getelf(dbg);
cfi = dwarf_getcfi_elf(elf);
if (cfi)
{
CFI_data cfiData;
cfiData.cfi = cfi;

cfi = dwarf_getcfi_elf( dwarf_getelf(dbg) );
if (cfi) {
cfi_data.push_back(cfi);
}
Dwarf_Off offset = 0, next_offset;
int res = 0;

auto e_ident = reinterpret_cast<const unsigned char*>(elf_getident(elf, NULL));
int i = section_id(elf);
assert(i!=-1);

do
{
Dwarf_CFI_Entry entry;
res = dwarf_next_cfi(e_ident, elf_getdata(elf_getscn(elf, i), NULL),
true, offset, &next_offset, &entry);
offset = next_offset;
if(res==0) cfiData.cfi_entries.push_back(entry);
}
while(res != 1);

cfi_data.push_back(cfiData);
}

// Verify if it got any dwarf data
if (!cfi_data.size()) {
fde_dwarf_status = dwarf_status_error;
}
Expand All @@ -419,36 +453,46 @@ void DwarfFrameParser::setupFdeData()


bool DwarfFrameParser::getFDE(Address pc, Dwarf_Frame* &frame,
Address &low, Address &high,
FrameErrors_t &err_result)
Address &low, Address &high, FrameErrors_t &err_result)
{
Dwarf_Addr lowpc = 0, hipc = 0;
dwarf_printf("Getting Frame for 0x%lx\n", pc);
bool found = false;
unsigned cur_fde;
for (cur_fde=0; cur_fde<cfi_data.size(); cur_fde++) {
int result = dwarf_cfi_addrframe(cfi_data[cur_fde],
(Dwarf_Addr) pc, &frame);

if (result == -1) {
dwarf_printf("\t Got ERROR return\n");
err_result = FE_Bad_Frame_Data;
return false;
}
Dwarf_Addr lowpc = 0, hipc = 0;
bool found = false;

dwarf_frame_info(frame, &lowpc, &hipc, NULL);
if (pc < lowpc || pc > hipc)
{
continue;
}
else
for (size_t cur_cfi=0; cur_cfi < cfi_data.size(); cur_cfi++)
{
for (size_t cur_entry =0; cur_entry < cfi_data[cur_cfi].cfi_entries.size(); cur_entry++)
{
auto& cfi_entry = cfi_data[cur_cfi].cfi_entries[cur_entry];
if(dwarf_cfi_cie_p(&cfi_entry))
{
continue;
}
lowpc = *cfi_entry.fde.start;
hipc = *cfi_entry.fde.end;

if (pc < lowpc || pc > hipc)
{
continue;
}

dwarf_printf("\t Got range 0x%lx..0x%lx\n", lowpc, hipc);

low = (Address) lowpc;
high = (Address) hipc;
if(!dwarf_cfi_addrframe(cfi_data[cur_cfi].cfi, pc, &frame))
{
continue;
}
found = true;
break;
}

if (found)
{
break;
}
}

if (!found)
Expand All @@ -460,10 +504,9 @@ bool DwarfFrameParser::getFDE(Address pc, Dwarf_Frame* &frame,
return true;
}

bool DwarfFrameParser::getDwarfReg(Dyninst::MachRegister reg,
Dwarf_Frame* frame,
Dwarf_Half &dwarf_reg,
FrameErrors_t & /*err_result*/)
bool DwarfFrameParser::getDwarfReg(
Dyninst::MachRegister reg, Dwarf_Frame* frame,
Dwarf_Half &dwarf_reg, FrameErrors_t & /*err_result*/)
{
if (reg == Dyninst::ReturnAddr) {
dwarf_reg = dwarf_frame_info(frame, NULL, NULL, NULL);
Expand Down

0 comments on commit 7a63dae

Please sign in to comment.