aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorOlivier Hainque <hainque@adacore.com>2007-04-06 11:15:36 +0200
committerArnaud Charlet <charlet@gcc.gnu.org>2007-04-06 11:15:36 +0200
commitc99c095f991024052fcf8d32d230ce448edc2d81 (patch)
treecbad8ec2d61270e4c4e4aa20909e6960da5c3d68 /gcc
parent42907632860e44cc8c8b49a0b74444f62791fb9c (diff)
downloadgcc-c99c095f991024052fcf8d32d230ce448edc2d81.zip
gcc-c99c095f991024052fcf8d32d230ce448edc2d81.tar.gz
gcc-c99c095f991024052fcf8d32d230ce448edc2d81.tar.bz2
adaint.c:
2007-04-06 Olivier Hainque <hainque@adacore.com> * adaint.c: (convert_addresses): Adjust prototype and dummy definition to expect an extra file_name argument. * gmem.c (__gnat_convert_addresses): Wrapper to convert_addresses, filling the now expected file_name argument with the appropriate argv[0] expansion. (__gnat_gmem_a2l_initialize, __gnat_gmem_read_next_frame): Use it. (tracebk): Array of void * instead of char *, corresponding to what convert_addresses expects. (exename): New static global, to hold the executable file name to be used in all convert_addresses invocations. (gmem_read_backtrace, __gnat_gmem_symbolic): Account for tracebk type change. (__gnat_gmem_a2l_initialize): Resolve exename. (__gnat_convert_addresses): Use exename as the convert_addresses file_name argument. * g-trasym.adb (Symbolic_Traceback): Adjust signature of imported "convert_addresses", now expecting a filename argument. Import the necessary entities to compute the filename to use and pass it to convert_addresses. From-SVN: r123544
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ada/adaint.c66
-rw-r--r--gcc/ada/g-trasym.adb90
-rw-r--r--gcc/ada/gmem.c52
3 files changed, 159 insertions, 49 deletions
diff --git a/gcc/ada/adaint.c b/gcc/ada/adaint.c
index dd2e0d6..9952bc8 100644
--- a/gcc/ada/adaint.c
+++ b/gcc/ada/adaint.c
@@ -324,6 +324,14 @@ to_ptr32 (char **ptr64)
#define MAYBE_TO_PTR32(argv) argv
#endif
+OS_Time
+__gnat_current_time
+ (void)
+{
+ time_t res = time (NULL);
+ return (OS_Time) res;
+}
+
void
__gnat_to_gm_time
(OS_Time *p_time,
@@ -418,8 +426,8 @@ __gnat_try_lock (char *dir, char *file)
TCHAR wfile[GNAT_MAX_PATH_LEN];
TCHAR wdir[GNAT_MAX_PATH_LEN];
- S2WS (wdir, dir, GNAT_MAX_PATH_LEN);
- S2WS (wfile, file, GNAT_MAX_PATH_LEN);
+ S2WSU (wdir, dir, GNAT_MAX_PATH_LEN);
+ S2WSU (wfile, file, GNAT_MAX_PATH_LEN);
_stprintf (wfull_path, _T("%s%c%s"), wdir, _T(DIR_SEPARATOR), wfile);
fd = _topen (wfull_path, O_CREAT | O_EXCL, 0600);
@@ -542,7 +550,7 @@ __gnat_get_current_dir (char *dir, int *length)
_tgetcwd (wdir, *length);
- WS2S (dir, wdir, GNAT_MAX_PATH_LEN);
+ WS2SU (dir, wdir, GNAT_MAX_PATH_LEN);
#elif defined (VMS)
/* Force Unix style, which is what GNAT uses internally. */
@@ -612,31 +620,44 @@ __gnat_get_debuggable_suffix_ptr (int *len, const char **value)
}
FILE *
-__gnat_fopen (char *path, char *mode)
+__gnat_fopen (char *path, char *mode, int encoding)
{
#if defined (_WIN32) && ! defined (__vxworks) && ! defined (CROSS_DIRECTORY_STRUCTURE)
TCHAR wpath[GNAT_MAX_PATH_LEN];
TCHAR wmode[10];
- S2WS (wpath, path, GNAT_MAX_PATH_LEN);
S2WS (wmode, mode, 10);
+
+ if (encoding == Encoding_UTF8)
+ S2WSU (wpath, path, GNAT_MAX_PATH_LEN);
+ else
+ S2WS (wpath, path, GNAT_MAX_PATH_LEN);
+
return _tfopen (wpath, wmode);
+#elif defined (VMS)
+ return decc$fopen (path, mode);
#else
return fopen (path, mode);
#endif
}
-
FILE *
-__gnat_freopen (char *path, char *mode, FILE *stream)
+__gnat_freopen (char *path, char *mode, FILE *stream, int encoding)
{
#if defined (_WIN32) && ! defined (__vxworks) && ! defined (CROSS_DIRECTORY_STRUCTURE)
TCHAR wpath[GNAT_MAX_PATH_LEN];
TCHAR wmode[10];
- S2WS (wpath, path, GNAT_MAX_PATH_LEN);
S2WS (wmode, mode, 10);
+
+ if (encoding == Encoding_UTF8)
+ S2WSU (wpath, path, GNAT_MAX_PATH_LEN);
+ else
+ S2WS (wpath, path, GNAT_MAX_PATH_LEN);
+
return _tfreopen (wpath, wmode, stream);
+#elif defined (VMS)
+ return decc$freopen (path, mode, stream);
#else
return freopen (path, mode, stream);
#endif
@@ -661,7 +682,7 @@ __gnat_open_read (char *path, int fmode)
{
TCHAR wpath[GNAT_MAX_PATH_LEN];
- S2WS (wpath, path, GNAT_MAX_PATH_LEN);
+ S2WSU (wpath, path, GNAT_MAX_PATH_LEN);
fd = _topen (wpath, O_RDONLY | o_fmode, 0444);
}
#else
@@ -702,7 +723,7 @@ __gnat_open_rw (char *path, int fmode)
{
TCHAR wpath[GNAT_MAX_PATH_LEN];
- S2WS (wpath, path, GNAT_MAX_PATH_LEN);
+ S2WSU (wpath, path, GNAT_MAX_PATH_LEN);
fd = _topen (wpath, O_RDWR | o_fmode, PERM);
}
#else
@@ -728,7 +749,7 @@ __gnat_open_create (char *path, int fmode)
{
TCHAR wpath[GNAT_MAX_PATH_LEN];
- S2WS (wpath, path, GNAT_MAX_PATH_LEN);
+ S2WSU (wpath, path, GNAT_MAX_PATH_LEN);
fd = _topen (wpath, O_WRONLY | O_CREAT | O_TRUNC | o_fmode, PERM);
}
#else
@@ -750,7 +771,7 @@ __gnat_create_output_file (char *path)
{
TCHAR wpath[GNAT_MAX_PATH_LEN];
- S2WS (wpath, path, GNAT_MAX_PATH_LEN);
+ S2WSU (wpath, path, GNAT_MAX_PATH_LEN);
fd = _topen (wpath, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, PERM);
}
#else
@@ -776,7 +797,7 @@ __gnat_open_append (char *path, int fmode)
{
TCHAR wpath[GNAT_MAX_PATH_LEN];
- S2WS (wpath, path, GNAT_MAX_PATH_LEN);
+ S2WSU (wpath, path, GNAT_MAX_PATH_LEN);
fd = _topen (wpath, O_WRONLY | O_CREAT | O_APPEND | o_fmode, PERM);
}
#else
@@ -804,7 +825,7 @@ __gnat_open_new (char *path, int fmode)
{
TCHAR wpath[GNAT_MAX_PATH_LEN];
- S2WS (wpath, path, GNAT_MAX_PATH_LEN);
+ S2WSU (wpath, path, GNAT_MAX_PATH_LEN);
fd = _topen (wpath, O_WRONLY | O_CREAT | O_EXCL | o_fmode, PERM);
}
#else
@@ -940,7 +961,7 @@ DIR* __gnat_opendir (char *name)
#ifdef __MINGW32__
TCHAR wname[GNAT_MAX_PATH_LEN];
- S2WS (wname, name, GNAT_MAX_PATH_LEN);
+ S2WSU (wname, name, GNAT_MAX_PATH_LEN);
return (DIR*)_topendir (wname);
#else
@@ -959,7 +980,7 @@ __gnat_readdir (DIR *dirp, char *buffer, int *len)
if (dirent != NULL)
{
- WS2S (buffer, dirent->d_name, GNAT_MAX_PATH_LEN);
+ WS2SU (buffer, dirent->d_name, GNAT_MAX_PATH_LEN);
*len = strlen (buffer);
return buffer;
@@ -1058,7 +1079,7 @@ __gnat_file_time_name (char *name)
time_t ret = -1;
TCHAR wname[GNAT_MAX_PATH_LEN];
- S2WS (wname, name, GNAT_MAX_PATH_LEN);
+ S2WSU (wname, name, GNAT_MAX_PATH_LEN);
HANDLE h = CreateFile
(wname, GENERIC_READ, FILE_SHARE_READ, 0,
@@ -1195,7 +1216,7 @@ __gnat_set_file_time_name (char *name, time_t time_stamp)
} t_write;
TCHAR wname[GNAT_MAX_PATH_LEN];
- S2WS (wname, name, GNAT_MAX_PATH_LEN);
+ S2WSU (wname, name, GNAT_MAX_PATH_LEN);
HANDLE h = CreateFile
(wname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
@@ -1462,7 +1483,7 @@ __gnat_stat (char *name, struct stat *statbuf)
int name_len;
TCHAR last_char;
- S2WS (wname, name, GNAT_MAX_PATH_LEN + 2);
+ S2WSU (wname, name, GNAT_MAX_PATH_LEN + 2);
name_len = _tcslen (wname);
if (name_len > GNAT_MAX_PATH_LEN)
@@ -1854,7 +1875,7 @@ win32_no_block_spawn (char *command, char *args[])
int wsize = csize * 2;
TCHAR *wcommand = (TCHAR *) xmalloc (wsize);
- S2WS (wcommand, full_command, wsize);
+ S2WSU (wcommand, full_command, wsize);
free (full_command);
@@ -2145,7 +2166,7 @@ __gnat_locate_exec_on_path (char *exec_name)
apath_val = alloca (EXPAND_BUFFER_SIZE);
- WS2S (apath_val, wapath_val, EXPAND_BUFFER_SIZE);
+ WS2SU (apath_val, wapath_val, EXPAND_BUFFER_SIZE);
return __gnat_locate_exec (exec_name, apath_val);
#else
@@ -2623,7 +2644,8 @@ _flush_cache()
version of this procedure in libaddr2line.a. */
void
-convert_addresses (void *addrs ATTRIBUTE_UNUSED,
+convert_addresses (const char *file_name ATTRIBUTE_UNUSED,
+ void *addrs ATTRIBUTE_UNUSED,
int n_addr ATTRIBUTE_UNUSED,
void *buf ATTRIBUTE_UNUSED,
int *len ATTRIBUTE_UNUSED)
diff --git a/gcc/ada/g-trasym.adb b/gcc/ada/g-trasym.adb
index e8f9122..117dcc2 100644
--- a/gcc/ada/g-trasym.adb
+++ b/gcc/ada/g-trasym.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1999-2005, AdaCore --
+-- Copyright (C) 1999-2006, AdaCore --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -44,38 +44,104 @@ package body GNAT.Traceback.Symbolic is
package TSL renames System.Soft_Links;
+ -- To perform the raw addresses to symbolic form translation we rely on a
+ -- libaddr2line symbolizer which examines debug info from a provided
+ -- executable file name, and an absolute path is needed to ensure the file
+ -- is always found. This is "__gnat_locate_exec_on_path (gnat_argv [0])"
+ -- for our executable file, a fairly heavy operation so we cache the
+ -- result.
+
+ Exename : System.Address;
+ -- Pointer to the name of the executable file to be used on all
+ -- invocations of the libaddr2line symbolization service.
+
+ Exename_Resolved : Boolean := False;
+ -- Flag to indicate whether we have performed the executable file name
+ -- resolution already. Relying on a not null Exename for this purpose
+ -- would be potentially inefficient as this is what we will get if the
+ -- resolution attempt fails.
+
------------------------
-- Symbolic_Traceback --
------------------------
function Symbolic_Traceback (Traceback : Tracebacks_Array) return String is
+
procedure convert_addresses
- (addrs : System.Address;
- n_addr : Integer;
- buf : System.Address;
- len : System.Address);
+ (filename : System.Address;
+ addrs : System.Address;
+ n_addrs : Integer;
+ buf : System.Address;
+ len : System.Address);
pragma Import (C, convert_addresses, "convert_addresses");
- -- This is the procedure version of the Ada aware addr2line that will
- -- use argv[0] as the executable containing the debug information.
+ -- This is the procedure version of the Ada aware addr2line. It places
+ -- in BUF a string representing the symbolic translation of the N_ADDRS
+ -- raw addresses provided in ADDRS, looked up in debug information from
+ -- FILENAME. LEN is filled with the result length.
+ --
-- This procedure is provided by libaddr2line on targets that support
- -- it. A dummy version is in a-adaint.c for other targets so that build
+ -- it. A dummy version is in adaint.c for other targets so that build
-- of shared libraries doesn't generate unresolved symbols.
--
-- Note that this procedure is *not* thread-safe.
+ type Argv_Array is array (0 .. 0) of System.Address;
+ gnat_argv : access Argv_Array;
+ pragma Import (C, gnat_argv, "gnat_argv");
+
+ function locate_exec_on_path
+ (c_exename : System.Address) return System.Address;
+ pragma Import (C, locate_exec_on_path, "__gnat_locate_exec_on_path");
+
Res : String (1 .. 256 * Traceback'Length);
Len : Integer;
+ use type System.Address;
+
begin
- if Traceback'Length > 0 then
- TSL.Lock_Task.all;
+ -- The symbolic translation of an empty set of addresses is the
+ -- the empty string.
+
+ if Traceback'Length <= 0 then
+ return "";
+ end if;
+
+ -- If our input set of raw addresses is not empty, resort to the
+ -- libaddr2line service to symbolize it all.
+
+ -- Compute, cache and provide the absolute path to our executable file
+ -- name as the binary file where the relevant debug information is to
+ -- be found. If the executable file name resolution fails, we have no
+ -- sensible basis to invoke the symbolizer at all.
+
+ -- Protect all this against concurrent accesses explicitely, as the
+ -- underlying services are potentially thread unsafe.
+
+ TSL.Lock_Task.all;
+
+ if not Exename_Resolved then
+ Exename := locate_exec_on_path (gnat_argv (0));
+ Exename_Resolved := True;
+ end if;
+
+ if Exename /= System.Null_Address then
convert_addresses
- (Traceback'Address, Traceback'Length, Res (1)'Address, Len'Address);
- TSL.Unlock_Task.all;
+ (Exename, Traceback'Address, Traceback'Length,
+ Res (1)'Address, Len'Address);
+ end if;
+
+ TSL.Unlock_Task.all;
+
+ -- Return what the addr2line symbolizer has produced if we have called
+ -- it (the executable name resolution succeeded), or an empty string
+ -- otherwise.
+
+ if Exename /= System.Null_Address then
return Res (1 .. Len);
else
return "";
end if;
+
end Symbolic_Traceback;
function Symbolic_Traceback (E : Exception_Occurrence) return String is
diff --git a/gcc/ada/gmem.c b/gcc/ada/gmem.c
index 74299ad..e45e12c 100644
--- a/gcc/ada/gmem.c
+++ b/gcc/ada/gmem.c
@@ -6,7 +6,7 @@
* *
* C Implementation File *
* *
- * Copyright (C) 2000-2003 Free Software Foundation, Inc. *
+ * Copyright (C) 2000-2006, Free Software Foundation, Inc. *
* *
* GNAT is free software; you can redistribute it and/or modify it under *
* terms of the GNU General Public License as published by the Free Soft- *
@@ -54,7 +54,7 @@ static FILE *gmemfile;
/* tb_len is the number of call level supported by this module */
#define tb_len 200
-static char * tracebk [tb_len];
+static void * tracebk [tb_len];
static int cur_tb_len, cur_tb_pos;
#define LOG_EOF '*'
@@ -67,8 +67,34 @@ struct struct_storage_elmt {
size_t Size;
};
-extern void
-convert_addresses (char *addrs[], int n_addr, void *buf, int *len);
+static void
+__gnat_convert_addresses (void *addrs[], int n_addrs, void *buf, int *len);
+/* Place in BUF a string representing the symbolic translation of N_ADDRS raw
+ addresses provided in ADDRS. LEN is filled with the result length.
+
+ This is a GNAT specific interface to the libaddr2line convert_addresses
+ routine. The latter examines debug info from a provided executable file
+ name to perform the translation into symbolic form of an input sequence of
+ raw binary addresses. It attempts to open the file from the provided name
+ "as is", so an an absolute path must be provided to ensure the file is
+ always found. We compute this name once, at initialization time. */
+
+static const char * exename = 0;
+
+extern void convert_addresses (const char * , void *[], int, void *, int *);
+extern char *__gnat_locate_exec_on_path (char *);
+/* ??? Both of these extern functions are prototyped in adaint.h, which
+ also refers to "time_t" hence needs complex extra header inclusions to
+ be satisfied on every target. */
+
+static void
+__gnat_convert_addresses (void *addrs[], int n_addrs, void *buf, int *len)
+{
+ if (exename != 0)
+ convert_addresses (exename, addrs, n_addrs, buf, len);
+ else
+ *len = 0;
+}
/* reads backtrace information from gmemfile placing them in tracebk
array. cur_tb_len is the size of this array
@@ -78,7 +104,7 @@ static void
gmem_read_backtrace (void)
{
fread (&cur_tb_len, sizeof (int), 1, gmemfile);
- fread (tracebk, sizeof (char *), cur_tb_len, gmemfile);
+ fread (tracebk, sizeof (void *), cur_tb_len, gmemfile);
cur_tb_pos = 0;
}
@@ -106,14 +132,11 @@ int __gnat_gmem_initialize (char *dumpname)
/* initialize addr2line library */
-void __gnat_gmem_a2l_initialize (char *exename)
+void __gnat_gmem_a2l_initialize (char *exearg)
{
- extern char **gnat_argv;
- char s [100];
- int l;
-
- gnat_argv [0] = exename;
- convert_addresses (tracebk, 1, s, &l);
+ /* Resolve the executable filename to use in later invocations of
+ the libaddr2line symbolization service. */
+ exename = __gnat_locate_exec_on_path (exearg);
}
/* Read next allocation of deallocation information from the GMEM file and
@@ -172,8 +195,7 @@ void __gnat_gmem_read_next_frame (void** addr)
void __gnat_gmem_symbolic (void * addr, char* buf, int* length)
{
- char* addresses [] = { (char*)addr };
- extern char** gnat_argv;
+ void * addresses [] = { addr };
- convert_addresses (addresses, 1, buf, length);
+ __gnat_convert_addresses (addresses, 1, buf, length);
}