[Ada] Display executable load address before traceback
Arnaud Charlet
charlet@adacore.com
Mon Oct 14 12:52:00 GMT 2013
This is useful for post-mortem traceback analysis on PIE platforms.
No new test, as this is platform specific.
Tested on x86_64-pc-linux-gnu, committed on trunk
2013-10-14 Tristan Gingold <gingold@adacore.com>
* adaint.c, adaint.h (__gnat_get_executable_load_address):
New function.
* a-exexda.adb (Append_Info_Basic_Exception_Traceback): Add
executable load address (Basic_Exception_Tback_Maxlength): Adjust.
-------------- next part --------------
Index: a-exexda.adb
===================================================================
--- a-exexda.adb (revision 203521)
+++ a-exexda.adb (working copy)
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, 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- --
@@ -206,6 +206,11 @@
pragma Export
(Ada, Exception_Message_Length, "__gnat_exception_msg_len");
+ function Get_Executable_Load_Address return System.Address;
+ pragma Import (C, Get_Executable_Load_Address,
+ "__gnat_get_executable_load_address");
+ -- Get the load address of the executable, or Null_Address if not known
+
-------------------------
-- Append_Info_Address --
-------------------------
@@ -377,17 +382,29 @@
-- As for Basic_Exception_Information:
BETB_Header : constant String := "Call stack traceback locations:";
+ LDAD_Header : constant String := "Load address: ";
procedure Append_Info_Basic_Exception_Traceback
(X : Exception_Occurrence;
Info : in out String;
Ptr : in out Natural)
is
+ Load_Address : Address;
begin
if X.Num_Tracebacks = 0 then
return;
end if;
+ -- The executable load address line
+
+ Load_Address := Get_Executable_Load_Address;
+ if Load_Address /= Null_Address then
+ Append_Info_String (LDAD_Header, Info, Ptr);
+ Append_Info_Address (Load_Address, Info, Ptr);
+ Append_Info_NL (Info, Ptr);
+ end if;
+
+ -- The traceback lines
Append_Info_String (BETB_Header, Info, Ptr);
Append_Info_NL (Info, Ptr);
@@ -407,11 +424,12 @@
function Basic_Exception_Tback_Maxlength
(X : Exception_Occurrence) return Natural
is
- Space_Per_Traceback : constant := 2 + 16 + 1;
+ Space_Per_Address : constant := 2 + 16 + 1;
-- Space for "0x" + HHHHHHHHHHHHHHHH + " "
begin
- return BETB_Header'Length + 1 +
- X.Num_Tracebacks * Space_Per_Traceback + 1;
+ return LDAD_Header'Length + Space_Per_Address +
+ BETB_Header'Length + 1 +
+ X.Num_Tracebacks * Space_Per_Address + 1;
end Basic_Exception_Tback_Maxlength;
---------------------------------------
Index: adaint.c
===================================================================
--- adaint.c (revision 203521)
+++ adaint.c (working copy)
@@ -3830,8 +3830,8 @@
extern void __main (void);
void __main (void) {}
-#endif
-#endif
+#endif /* RTSS */
+#endif /* RTX */
#if defined (__ANDROID__)
@@ -3889,7 +3889,7 @@
CPU_SET_S (cpu - 1, count, set);
}
-#else
+#else /* !CPU_ALLOC */
/* Static cpu sets */
@@ -3919,8 +3919,59 @@
CPU by a 0, so we need to adjust. */
CPU_SET (cpu - 1, set);
}
+#endif /* !CPU_ALLOC */
+#endif /* linux */
+
+/* Return the load address of the executable, or 0 if not known. In the
+ specific case of error, (void *)-1 can be returned. Beware: this unit may
+ be in a shared library. As low-level units are needed, we allow #include
+ here. */
+
+#if defined (__APPLE__)
+#include <mach-o/dyld.h>
+#elif defined (__linux__)
+#include <link.h>
+#elif defined (__AIX__)
+#include <sys/ldr.h>
#endif
+
+const void *
+__gnat_get_executable_load_address (void)
+{
+#if defined (__APPLE__)
+ return _dyld_get_image_header (0);
+
+#elif defined (__linux__)
+ struct link_map *map = _r_debug.r_map;
+
+ return (const void *)map->l_addr;
+
+#elif defined (__AIX__)
+ /* Unfortunately, AIX wants to return the info for all loaded objects,
+ so we need to increase the buffer if too small. */
+ size_t blen = 4096;
+ int status;
+
+ while (1)
+ {
+ char buf[blen];
+
+ status = loadquery (L_GETINFO, buf, blen);
+ if (status == 0)
+ {
+ struct ldinfo *info = (struct ld_info *)buf;
+ return info->ldinfo_textorg;
+ }
+ blen = blen * 2;
+
+ /* Avoid stack overflow. */
+ if (blen > 40 * 1024)
+ return (const void *)-1;
+ }
+#else
+ return NULL;
#endif
+}
#ifdef __cplusplus
}
Index: adaint.h
===================================================================
--- adaint.h (revision 203521)
+++ adaint.h (working copy)
@@ -287,6 +287,8 @@
extern int __gnat_binder_supports_auto_init (void);
extern int __gnat_sals_init_using_constructors (void);
+extern const void * __gnat_get_executable_load_address (void);
+
#ifdef __cplusplus
}
#endif
More information about the Gcc-patches
mailing list