Mercurial > hg > CbC > CbC_gcc
diff gcc/ada/libgnat/s-tsmona__linux.adb @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gcc/ada/libgnat/s-tsmona__linux.adb Fri Oct 27 22:46:09 2017 +0900 @@ -0,0 +1,188 @@ +------------------------------------------------------------------------------ +-- -- +-- 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-2017, 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; + +with System.Address_Operations; use System.Address_Operations; + +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 : 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 + if dladdr (Addr.all, 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 + Addr.all := SubA (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;