This is the mail archive of the
gdb@sourceware.org
mailing list for the GDB project.
Re: setting a breakpoint on a dll, relative path or absolute path issue
On 2011-6-14 11:10, Asm warrior wrote:
On 2011-6-14 0:59, Eli Zaretskii wrote:
Date: Mon, 13 Jun 2011 14:29:28 +0800
> From: Asm warrior<asmwarrior@gmail.com>
> CC: "John E. / TDM"<tdragon@tdragon.net>, Eli Zaretskii<eliz@gnu.org>,
> jan.kratochvil@redhat.com,keiths@redhat.com
>
> When loop on the symbols. I found that at one loop, I get
>
> s->filename = "../../src/common/string.cpp"
> s->dirname = "D:\code\wxWidgets-2.8.12\build\msw"
>
> But too badly, the result
> s->fullname =
> "D:\code\wxWidgets-2.8.12\build\msw/../../src/common/string.cpp"
>
> This is the reason about the issue, if the result is:
> "D:\code\wxWidgets-2.8.12/src/common/string.cpp"
> Then, this problem can be fixed.
>
> I'm not sure why gdb does not give a cannical filename, but still
leaves
> the "../../" in the result.
Because the function that canonicalizes the file name does not support
backslashes correctly?
By reading the gdb source, mostly in file: source.c and symtab.c
I found that in the function:
char *
symtab_to_fullname (struct symtab *s)
{
int r;
if (!s)
return NULL;
/* Don't check s->fullname here, the file could have been
deleted/moved/..., look for it again. */
r = find_and_open_source (s->filename, s->dirname, &s->fullname);
if (r >= 0)
{
close (r);
return s->fullname;
}
return NULL;
}
This function try to check if the file exists.
The lucky thing is: The function call:
open("D:\code\wxWidgets-2.8.12\build\msw/../../src/common/string.cpp") ;
works OK.
Though the file path is not satisfied by me, but it just satisfied by
open() function, Yeah, the open() function can internally do a path
canonization on its parameter, and gdb knows that this file exists and
can be opened.
As I know, GDB does not do a canonization on any returned file names. (I
can't find any code snippet doing this kind of work).
Well, the proposed method can be: (see below)
char *
symtab_to_fullname (struct symtab *s)
{
int r;
if (!s)
return NULL;
/* Don't check s->fullname here, the file could have been
deleted/moved/..., look for it again. */
r = find_and_open_source (s->filename, s->dirname, &s->fullname);
if (r >= 0)
{
close (r);
*******
DoSomePathCanonization(&s->fullname);
*******
return s->fullname;
}
return NULL;
}
This way, the returned string can be:
"D:/code/wxWidgets-2.8.12/src/common/string.cpp"
BTW:Did you thing that Any one would like to set a breakpoint by using
name containing many "../../"?
I can hardly think one would like to set a break point by entering this
command:
b "D:\code\wxWidgets-2.8.12\build\msw/../../src/common/string.cpp:165"
I personally think this is too ugly.
Any ideas?
Asmwarrior
ollydbg from codeblocks' forum
Ok, now I try to implement this, I found the is a function do the
canonicalize filepath.
under gdb\utils.c
char *
gdb_realpath (const char *filename)
{
/* Method 1: The system has a compile time upper bound on a filename
path. Use that and realpath() to canonicalize the name. This is
the most common case. Note that, if there isn't a compile time
upper bound, you want to avoid realpath() at all costs. */
#if defined(HAVE_REALPATH)
{
# if defined (PATH_MAX)
char buf[PATH_MAX];
# define USE_REALPATH
# elif defined (MAXPATHLEN)
char buf[MAXPATHLEN];
# define USE_REALPATH
# endif
# if defined (USE_REALPATH)
const char *rp = realpath (filename, buf);
if (rp == NULL)
rp = filename;
return xstrdup (rp);
# endif
}
#endif /* HAVE_REALPATH */
/* Method 2: The host system (i.e., GNU) has the function
canonicalize_file_name() which malloc's a chunk of memory and
returns that, use that. */
#if defined(HAVE_CANONICALIZE_FILE_NAME)
{
char *rp = canonicalize_file_name (filename);
if (rp == NULL)
return xstrdup (filename);
else
return rp;
}
#endif
/* FIXME: cagney/2002-11-13:
Method 2a: Use realpath() with a NULL buffer. Some systems, due
to the problems described in method 3, have modified their
realpath() implementation so that it will allocate a buffer when
NULL is passed in. Before this can be used, though, some sort of
configure time test would need to be added. Otherwize the code
will likely core dump. */
/* Method 3: Now we're getting desperate! The system doesn't have a
compile time buffer size and no alternative function. Query the
OS, using pathconf(), for the buffer limit. Care is needed
though, some systems do not limit PATH_MAX (return -1 for
pathconf()) making it impossible to pass a correctly sized buffer
to realpath() (it could always overflow). On those systems, we
skip this. */
#if defined (HAVE_REALPATH) && defined (HAVE_UNISTD_H) &&
defined(HAVE_ALLOCA)
{
/* Find out the max path size. */
long path_max = pathconf ("/", _PC_PATH_MAX);
if (path_max > 0)
{
/* PATH_MAX is bounded. */
char *buf = alloca (path_max);
char *rp = realpath (filename, buf);
return xstrdup (rp ? rp : filename);
}
}
#endif
/* This system is a lost cause, just dup the buffer. */
return xstrdup (filename);
}
But I found another function in:
gdb\libiberty\lrealpath.c
char *
lrealpath (const char *filename)
{
/* Method 1: The system has a compile time upper bound on a filename
path. Use that and realpath() to canonicalize the name. This is
the most common case. Note that, if there isn't a compile time
upper bound, you want to avoid realpath() at all costs. */
#if defined(REALPATH_LIMIT)
{
char buf[REALPATH_LIMIT];
const char *rp = realpath (filename, buf);
if (rp == NULL)
rp = filename;
return strdup (rp);
}
#endif /* REALPATH_LIMIT */
/* Method 2: The host system (i.e., GNU) has the function
canonicalize_file_name() which malloc's a chunk of memory and
returns that, use that. */
#if defined(HAVE_CANONICALIZE_FILE_NAME)
{
char *rp = canonicalize_file_name (filename);
if (rp == NULL)
return strdup (filename);
else
return rp;
}
#endif
/* Method 3: Now we're getting desperate! The system doesn't have a
compile time buffer size and no alternative function. Query the
OS, using pathconf(), for the buffer limit. Care is needed
though, some systems do not limit PATH_MAX (return -1 for
pathconf()) making it impossible to pass a correctly sized buffer
to realpath() (it could always overflow). On those systems, we
skip this. */
#if defined (HAVE_REALPATH) && defined (HAVE_UNISTD_H)
{
/* Find out the max path size. */
long path_max = pathconf ("/", _PC_PATH_MAX);
if (path_max > 0)
{
/* PATH_MAX is bounded. */
char *buf, *rp, *ret;
buf = (char *) malloc (path_max);
if (buf == NULL)
return NULL;
rp = realpath (filename, buf);
ret = strdup (rp ? rp : filename);
free (buf);
return ret;
}
}
#endif
/* The MS Windows method. If we don't have realpath, we assume we
don't have symlinks and just canonicalize to a Windows absolute
path. GetFullPath converts ../ and ./ in relative paths to
absolute paths, filling in current drive if one is not given
or using the current directory of a specified drive (eg, "E:foo").
It also converts all forward slashes to back slashes. */
#if defined (_WIN32)
{
char buf[MAX_PATH];
char* basename;
DWORD len = GetFullPathName (filename, MAX_PATH, buf, &basename);
if (len == 0 || len > MAX_PATH - 1)
return strdup (filename);
else
{
/* The file system is case-preserving but case-insensitive,
Canonicalize to lowercase, using the codepage associated
with the process locale. */
CharLowerBuff (buf, len);
return strdup (buf);
}
}
#endif
/* This system is a lost cause, just duplicate the filename. */
return strdup (filename);
}
-------------------------------------------------------
Did you think we should add the "MS Windows method." in
gdb\libiberty\lrealpath.c to the char * gdb_realpath (const char
*filename) function body?
As currently, it just do a strdup(filename) under MinGW32 (Windows).
asmwarrior
ollydbg from codeblocks' forum