update to ida 7.6, add builds
This commit is contained in:
171
idasdk76/plugins/dwarf/look_for_debug_file.cpp
Normal file
171
idasdk76/plugins/dwarf/look_for_debug_file.cpp
Normal file
@@ -0,0 +1,171 @@
|
||||
//-------------------------------------------------------------------------
|
||||
// Mimic GDB's debug file-seeking mechanism. Let:
|
||||
// PATH be for-each components of the full DWARF_DEBUG_FILE_DIRECTORY.
|
||||
// BIN be the full path to the binary file.
|
||||
// DLINK the value of the section ".gnu_debuglink"
|
||||
// BLDID build ID from note section GNU/3
|
||||
// BLDCAR the lowercase hex-formatted value of the first byte of BLDID
|
||||
// BLDCDR the lowercase hex-formatted value of the remaining bytes of BLDID
|
||||
//
|
||||
// 1) Look for file by build ID
|
||||
// foreach PATH in DWARF_DEBUG_FILE_DIRECTORY:
|
||||
// if $PATH/.build-id/$BLDCAR/$BLDCRD.debug exists and matches:
|
||||
// found!
|
||||
// 2) If not found, look for file by debug link
|
||||
// if dir($BIN)/$DLINK exists and matches:
|
||||
// found!
|
||||
// if dir($BIN)/.debug/$DLINK exists and matches:
|
||||
// found!
|
||||
// foreach PATH in DWARF_DEBUG_FILE_DIRECTORY:
|
||||
// if $PATH/dir($BIN)/$DLINK exists and matches:
|
||||
// found!
|
||||
class debug_info_file_visitor_t
|
||||
{
|
||||
public:
|
||||
char fullpath[MAXSTR]; // current path
|
||||
enum checkmethod_t
|
||||
{
|
||||
BUILDID,
|
||||
DEBUGLINK
|
||||
};
|
||||
|
||||
// visit fullpath
|
||||
// returns 0 - continue to search
|
||||
virtual int visit_fullpath(checkmethod_t check_method)
|
||||
{
|
||||
int code = 0;
|
||||
if ( qfileexist(fullpath) )
|
||||
{
|
||||
code = 1;
|
||||
if ( check_method == DEBUGLINK )
|
||||
code = check_debuglink_crc32() ? 1 : 0;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
int call_visit_fullpath(checkmethod_t check_method)
|
||||
{
|
||||
int code = visit_fullpath(check_method);
|
||||
debugout("debug_info_file_visitor_t::visit_fullpath(check_method=%s), fullpath=%s => %d\n",
|
||||
check_method == BUILDID ? "BUILDID" : "DEBUGLINK",
|
||||
fullpath,
|
||||
code);
|
||||
return code;
|
||||
}
|
||||
|
||||
debug_info_file_visitor_t(
|
||||
const char *_glbl_deb_dirs, // global debug directories
|
||||
bool from_envvar, // taken from environment variable
|
||||
const char *_path_to_binary, // binary's absolute file name
|
||||
const char *_debuglink, // name of the separate debug info file
|
||||
uint32 _debuglink_crc32, // CRC32 of the separate debug info file
|
||||
const char *_buildid) // build ID
|
||||
: path_to_binary(_path_to_binary),
|
||||
debuglink(_debuglink),
|
||||
buildid(_buildid),
|
||||
debuglink_crc32(_debuglink_crc32)
|
||||
{
|
||||
fullpath[0] = '\0';
|
||||
const char *sep = from_envvar ? DELIMITER : ";"; //-V583
|
||||
char buf[QMAXPATH];
|
||||
qstrncpy(buf, _glbl_deb_dirs, sizeof(buf));
|
||||
char *saved_ptr;
|
||||
char *p = qstrtok(buf, sep, &saved_ptr);
|
||||
while ( p != NULL )
|
||||
{
|
||||
glbl_deb_dirs.push_back(p);
|
||||
p = qstrtok(NULL, sep, &saved_ptr);
|
||||
}
|
||||
}
|
||||
virtual ~debug_info_file_visitor_t() {}
|
||||
|
||||
// accept visitor
|
||||
// stop searching if visitor returns non-zero,
|
||||
// returns visitor's result
|
||||
int accept(void)
|
||||
{
|
||||
int code = 0;
|
||||
|
||||
// Look for file by build ID
|
||||
if ( !glbl_deb_dirs.empty() && !buildid.empty() )
|
||||
{
|
||||
// looks in the .build-id subdirectory of each one of the global debug directories
|
||||
// for a file named nn/nnnnnnnn.debug,
|
||||
// where nn are the first 2 hex characters of the build ID bit string,
|
||||
// and nnnnnnnn are the rest of the bit string
|
||||
qstring bid_car(buildid.c_str(), 2);
|
||||
qstring bid_cdr(buildid.c_str() + 2);
|
||||
bid_cdr.append(".debug");
|
||||
|
||||
for ( qstrvec_t::const_iterator p=glbl_deb_dirs.begin(); p != glbl_deb_dirs.end(); ++p )
|
||||
{
|
||||
qmakepath(fullpath, sizeof(fullpath), p->c_str(), ".build-id", bid_car.c_str(), bid_cdr.c_str(), NULL);
|
||||
code = call_visit_fullpath(BUILDID);
|
||||
if ( code != 0 )
|
||||
goto END;
|
||||
}
|
||||
}
|
||||
|
||||
// If not found, look for file by debug link
|
||||
if ( !debuglink.empty() )
|
||||
{
|
||||
char bindir[QMAXPATH];
|
||||
if ( qdirname(bindir, sizeof(bindir), path_to_binary.c_str()) )
|
||||
{
|
||||
// in the directory of the executable file
|
||||
qmakepath(fullpath, sizeof(fullpath), bindir, debuglink.c_str(), NULL);
|
||||
code = call_visit_fullpath(DEBUGLINK);
|
||||
if ( code != 0 )
|
||||
goto END;
|
||||
|
||||
// then in a subdirectory of that directory named .debug
|
||||
qmakepath(fullpath, sizeof(fullpath), bindir, ".debug", debuglink.c_str(), NULL);
|
||||
code = call_visit_fullpath(DEBUGLINK);
|
||||
if ( code != 0 )
|
||||
goto END;
|
||||
|
||||
// and finally under each one of the global debug directories,
|
||||
// in a subdirectory whose name is identical to the leading directories
|
||||
// of the executable's absolute file name
|
||||
for ( qstrvec_t::const_iterator p=glbl_deb_dirs.begin(); p != glbl_deb_dirs.end(); ++p )
|
||||
{
|
||||
qmakepath(fullpath, sizeof(fullpath), p->c_str(), bindir, debuglink.c_str(), NULL);
|
||||
code = call_visit_fullpath(DEBUGLINK);
|
||||
if ( code != 0 )
|
||||
goto END;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
END:
|
||||
return code;
|
||||
}
|
||||
|
||||
// check debuglink file CRC32
|
||||
bool check_debuglink_crc32(void)
|
||||
{
|
||||
linput_t *li = open_linput(fullpath, false);
|
||||
uint32 crc32 = calc_file_crc32(li);
|
||||
close_linput(li);
|
||||
return debuglink_crc32 == crc32;
|
||||
}
|
||||
|
||||
private:
|
||||
qstrvec_t glbl_deb_dirs;
|
||||
const qstring path_to_binary;
|
||||
const qstring debuglink;
|
||||
const qstring buildid;
|
||||
uint32 debuglink_crc32;
|
||||
|
||||
AS_PRINTF(2, 3) void debugout(const char *format, ...)
|
||||
{
|
||||
if ( (debug & LOOK_FOR_DEBUG_FILE_DEBUG_FLAG) != 0 )
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
vmsg(format, va);
|
||||
va_end(va);
|
||||
}
|
||||
}
|
||||
};
|
||||
#undef DIFV_DEB
|
||||
Reference in New Issue
Block a user