1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
|
------------------------------------------------------------------------------
-- --
-- GNAT RUN-TIME COMPONENTS --
-- --
-- G N A T . T R A C E B A C K . S Y M B O L I C . M O D U L E _ N A M E --
-- --
-- B o d y --
-- --
-- Copyright (C) 2012-2018, 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- --
-- ware Foundation; either version 3, or (at your option) any later ver- --
-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. --
-- --
-- As a special exception under Section 7 of GPL version 3, you are granted --
-- additional permissions described in the GCC Runtime Library Exception, --
-- version 3.1, as published by the Free Software Foundation. --
-- --
-- You should have received a copy of the GNU General Public License and --
-- a copy of the GCC Runtime Library Exception along with this program; --
-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
-- <http://www.gnu.org/licenses/>. --
-- --
-- GNAT was originally developed by the GNAT team at New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc. --
-- --
------------------------------------------------------------------------------
-- This is the GNU/Linux specific version of this package
with Interfaces.C; use Interfaces.C;
separate (System.Traceback.Symbolic)
package body Module_Name is
pragma Linker_Options ("-ldl");
function Is_Shared_Lib (Base : Address) return Boolean;
-- Returns True if a shared library
-- The principle is:
-- 1. We get information about the module containing the address.
-- 2. We check that the full pathname is pointing to a shared library.
-- 3. for shared libraries, we return the non relocated address (so
-- the absolute address in the shared library).
-- 4. we also return the full pathname of the module containing this
-- address.
-------------------
-- Is_Shared_Lib --
-------------------
function Is_Shared_Lib (Base : Address) return Boolean is
EI_NIDENT : constant := 16;
type u16 is mod 2 ** 16;
-- Just declare the needed header information, we just need to read the
-- type encoded in the second field.
type Elf32_Ehdr is record
e_ident : char_array (1 .. EI_NIDENT);
e_type : u16;
end record;
ET_DYN : constant := 3; -- A shared lib if e_type = ET_DYN
Header : Elf32_Ehdr;
pragma Import (Ada, Header);
-- Suppress initialization in Normalized_Scalars mode
for Header'Address use Base;
begin
return Header.e_type = ET_DYN;
exception
when others =>
return False;
end Is_Shared_Lib;
---------------------------------
-- Build_Cache_For_All_Modules --
---------------------------------
procedure Build_Cache_For_All_Modules is
type link_map;
type link_map_acc is access all link_map;
pragma Convention (C, link_map_acc);
type link_map is record
l_addr : Address;
-- Base address of the shared object
l_name : Address;
-- Null-terminated absolute file name
l_ld : Address;
-- Dynamic section
l_next, l_prev : link_map_acc;
-- Chain
end record;
pragma Convention (C, link_map);
type r_debug_type is record
r_version : Integer;
r_map : link_map_acc;
end record;
pragma Convention (C, r_debug_type);
r_debug : r_debug_type;
pragma Import (C, r_debug, "_r_debug");
lm : link_map_acc;
begin
lm := r_debug.r_map;
while lm /= null loop
if Big_String_Conv.To_Pointer (lm.l_name) (1) /= ASCII.NUL then
-- Discard non-file (like the executable itself or the gate).
Add_Module_To_Cache (Value (lm.l_name));
end if;
lm := lm.l_next;
end loop;
end Build_Cache_For_All_Modules;
---------
-- Get --
---------
function Get (Addr : System.Address;
Load_Addr : access System.Address)
return String
is
-- Dl_info record for Linux, used to get sym reloc offset
type Dl_info is record
dli_fname : System.Address;
dli_fbase : System.Address;
dli_sname : System.Address;
dli_saddr : System.Address;
end record;
function dladdr
(addr : System.Address;
info : not null access Dl_info) return int;
pragma Import (C, dladdr, "dladdr");
-- This is a Linux extension and not POSIX
info : aliased Dl_info;
begin
Load_Addr.all := System.Null_Address;
if dladdr (Addr, info'Access) /= 0 then
-- If we have a shared library we need to adjust the address to
-- be relative to the base address of the library.
if Is_Shared_Lib (info.dli_fbase) then
Load_Addr.all := info.dli_fbase;
end if;
return Value (info.dli_fname);
-- Not found, fallback to executable name
else
return "";
end if;
exception
when others =>
return "";
end Get;
------------------
-- Is_Supported --
------------------
function Is_Supported return Boolean is
begin
return True;
end Is_Supported;
end Module_Name;
|