00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "libdwarf.h"
00032 #include "elf/h/Elf_X.h"
00033 #include "dwarf/h/dwarfHandle.h"
00034 #include "dwarf/h/dwarfFrameParser.h"
00035 #include "common/h/debug_common.h"
00036 #include <cstring>
00037
00038 using namespace Dyninst;
00039 using namespace Dwarf;
00040 using namespace std;
00041
00042 void DwarfHandle::defaultDwarfError(Dwarf_Error , Dwarf_Ptr) {
00043
00044 }
00045
00046 Dwarf_Handler DwarfHandle::defaultErrFunc = DwarfHandle::defaultDwarfError;
00047
00048 DwarfHandle::DwarfHandle(string filename_, Elf_X *file_,
00049 Dwarf_Handler err_func_, Dwarf_Ptr err_data_) :
00050 init_dwarf_status(dwarf_status_uninitialized),
00051 dbg_file_data(NULL),
00052 file_data(NULL),
00053 line_data(NULL),
00054 type_data(NULL),
00055 frame_data(NULL),
00056 file(file_),
00057 dbg_file(NULL),
00058 err_func(err_func_),
00059 err_data(err_data_),
00060 filename(filename_)
00061 {
00062
00063 locate_dbg_file();
00064 }
00065
00066 void DwarfHandle::locate_dbg_file()
00067 {
00068 char *buffer;
00069 unsigned long buffer_size;
00070 bool result = file->findDebugFile(filename, debug_filename, buffer, buffer_size);
00071 if (!result)
00072 return;
00073 dbg_file = Elf_X::newElf_X(buffer, buffer_size, debug_filename);
00074 if (!dbg_file->isValid()) {
00075 dwarf_printf("Invalid ELF file for debug info: %s\n", debug_filename.c_str());
00076 dbg_file->end();
00077 dbg_file = NULL;
00078 }
00079 }
00080
00081 bool DwarfHandle::init_dbg()
00082 {
00083 int status;
00084 Dwarf_Error err;
00085 if (init_dwarf_status == dwarf_status_ok) {
00086 return true;
00087 }
00088
00089 if (init_dwarf_status == dwarf_status_error) {
00090 return false;
00091 }
00092
00093 status = dwarf_elf_init(file->e_elfp(), DW_DLC_READ,
00094 err_func, err_data, &file_data, &err);
00095 if (status != DW_DLV_OK) {
00096 init_dwarf_status = dwarf_status_error;
00097 return false;
00098 }
00099
00100 if (dbg_file) {
00101 status = dwarf_elf_init(dbg_file->e_elfp(), DW_DLC_READ,
00102 err_func, err_data, &dbg_file_data, &err);
00103 if (status != DW_DLV_OK) {
00104 init_dwarf_status = dwarf_status_error;
00105 return false;
00106 }
00107
00108
00109 line_data = &dbg_file_data;
00110 type_data = &dbg_file_data;
00111
00112 if (hasFrameData(dbg_file))
00113 frame_data = &dbg_file_data;
00114 else
00115 frame_data = &file_data;
00116 }
00117 else {
00118
00119 line_data = &file_data;
00120 type_data = &file_data;
00121 frame_data = &file_data;
00122 }
00123
00124 Dyninst::Architecture arch;
00125 switch (file->e_machine()) {
00126 case EM_386:
00127 arch = Arch_x86;
00128 break;
00129 case EM_X86_64:
00130 arch = Arch_x86_64;
00131 break;
00132 case EM_PPC:
00133 arch = Arch_ppc32;
00134 break;
00135 case EM_PPC64:
00136 arch = Arch_ppc64;
00137 break;
00138 default:
00139 assert(0 && "Unsupported archiecture in ELF file.");
00140 }
00141 sw = Dwarf::DwarfFrameParser::create(*frame_data, arch);
00142
00143 init_dwarf_status = dwarf_status_ok;
00144 return true;
00145 }
00146
00147 const char* frame_section_names[] = { ".debug_frame", ".eh_frame", NULL };
00148 bool DwarfHandle::hasFrameData(Elf_X *e)
00149 {
00150 unsigned short shstrtab_idx = e->e_shstrndx();
00151 Elf_X_Shdr &shstrtab = e->get_shdr(shstrtab_idx);
00152 if (!shstrtab.isValid())
00153 return false;
00154 Elf_X_Data data = shstrtab.get_data();
00155 if (!data.isValid())
00156 return false;
00157 const char *shnames = data.get_string();
00158
00159 unsigned short num_sections = e->e_shnum();
00160 for (unsigned i = 0; i < num_sections; i++) {
00161 Elf_X_Shdr &shdr = e->get_shdr(i);
00162 if (!shdr.isValid())
00163 continue;
00164 if (shdr.sh_type() == SHT_NOBITS)
00165 continue;
00166 unsigned long name_idx = shdr.sh_name();
00167 for (const char **s = frame_section_names; *s; s++) {
00168 if (strcmp(*s, shnames + name_idx) == 0) {
00169 return true;
00170 }
00171 }
00172 }
00173 return false;
00174 }
00175
00176 Elf_X *DwarfHandle::origFile()
00177 {
00178 return file;
00179 }
00180
00181 Elf_X *DwarfHandle::debugLinkFile()
00182 {
00183 return dbg_file;
00184 }
00185
00186 Dwarf_Debug *DwarfHandle::line_dbg()
00187 {
00188 if (!init_dbg())
00189 return NULL;
00190 return line_data;
00191 }
00192
00193 Dwarf_Debug *DwarfHandle::type_dbg()
00194 {
00195 if (!init_dbg())
00196 return NULL;
00197 return type_data;
00198 }
00199
00200 Dwarf_Debug *DwarfHandle::frame_dbg()
00201 {
00202 if (!init_dbg())
00203 return NULL;
00204 return frame_data;
00205 }
00206
00207
00208 DwarfHandle::~DwarfHandle()
00209 {
00210 if (init_dwarf_status != dwarf_status_ok)
00211 return;
00212
00213 Dwarf_Error err;
00214 if (dbg_file_data)
00215 dwarf_finish(dbg_file_data, &err);
00216 if (file_data)
00217 dwarf_finish(file_data, &err);
00218 }
00219
00220 map<std::string, DwarfHandle::ptr> DwarfHandle::all_dwarf_handles;
00221 DwarfHandle::ptr DwarfHandle::createDwarfHandle(string filename_, Elf_X *file_,
00222 Dwarf_Handler err_func_, Dwarf_Ptr err_data_)
00223 {
00224 map<string, DwarfHandle::ptr>::iterator i;
00225 i = all_dwarf_handles.find(filename_);
00226 if (i != all_dwarf_handles.end()) {
00227 return i->second;
00228 }
00229
00230 DwarfHandle::ptr ret = DwarfHandle::ptr(new DwarfHandle(filename_, file_, err_func_, err_data_));
00231 all_dwarf_handles.insert(make_pair(filename_, ret));
00232 return ret;
00233 }
00234
00235 DwarfFrameParserPtr DwarfHandle::frameParser() {
00236 return sw;
00237 }