Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:33

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (c) 2019 Chris Johns <chrisj@rtems.org>.
0005  * All rights reserved.
0006  *
0007  * Redistribution and use in source and binary forms, with or without
0008  * modification, are permitted provided that the following conditions
0009  * are met:
0010  * 1. Redistributions of source code must retain the above copyright
0011  *    notice, this list of conditions and the following disclaimer.
0012  * 2. Redistributions in binary form must reproduce the above copyright
0013  *    notice, this list of conditions and the following disclaimer in the
0014  *    documentation and/or other materials provided with the distribution.
0015  *
0016  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0017  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0018  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0019  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0020  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0021  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0022  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0023  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0024  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0025  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0026  * POSSIBILITY OF SUCH DAMAGE.
0027  */
0028 
0029 #define TEST_TRACE 0
0030 #if TEST_TRACE
0031  #define DEBUG_TRACE (RTEMS_RTL_TRACE_DETAIL | \
0032                       RTEMS_RTL_TRACE_WARNING | \
0033                       RTEMS_RTL_TRACE_LOAD | \
0034                       RTEMS_RTL_TRACE_UNLOAD | \
0035                       RTEMS_RTL_TRACE_SYMBOL | \
0036                       RTEMS_RTL_TRACE_RELOC | \
0037                       RTEMS_RTL_TRACE_ALLOCATOR | \
0038                       RTEMS_RTL_TRACE_UNRESOLVED | \
0039                       RTEMS_RTL_TRACE_ARCHIVES | \
0040                       RTEMS_RTL_TRACE_DEPENDENCY | \
0041                       RTEMS_RTL_TRACE_LOAD_SECT | \
0042                       RTEMS_RTL_TRACE_BIT_ALLOC)
0043  #define DL09_DEBUG_TRACE DEBUG_TRACE /* RTEMS_RTL_TRACE_ALL */
0044  #define DL09_RTL_CMDS    1
0045 #else
0046  #define DL09_DEBUG_TRACE 0
0047  #define DL09_RTL_CMDS    0
0048 #endif
0049 
0050 #include <dlfcn.h>
0051 
0052 #include "dl-load.h"
0053 
0054 #include <tmacros.h>
0055 
0056 #include <rtems/malloc.h>
0057 #include <rtems/rtl/rtl-shell.h>
0058 #include <rtems/rtl/rtl-trace.h>
0059 
0060 extern void rtems_shell_print_heap_info(
0061   const char             *c,
0062   const Heap_Information *h
0063 );
0064 
0065 typedef struct
0066 {
0067   void* handle;
0068   void* space;
0069 } objects;
0070 
0071 typedef struct
0072 {
0073   const char* name;
0074   bool        has_unresolved;
0075   size_t      space;
0076 } object_def;
0077 
0078 #define MBYTES(_m) ((_m) * 1024UL * 1024UL)
0079 #define NUMOF(_a)  (sizeof(_a) / sizeof(_a[0]))
0080 
0081 typedef int (*call_sig)(void);
0082 
0083 static void dl_load_dump (void)
0084 {
0085 #if DL09_RTL_CMDS
0086   char* list[] = { "rtl", "list", NULL };
0087   char* sym[] = { "rtl", "sym", NULL };
0088   Heap_Information_block info;
0089   malloc_info( &info );
0090   printf ("RTL List:\n");
0091   rtems_rtl_shell_command (2, list);
0092   printf ("RTL Sym:\n");
0093   rtems_rtl_shell_command (2, sym);
0094   printf ("Malloc:\n");
0095   rtems_shell_print_heap_info("free", &info.Free);
0096 #endif
0097 }
0098 
0099 static void dl_check_resolved(void* handle, bool has_unresolved)
0100 {
0101   int unresolved = 0;
0102   rtems_test_assert (dlinfo (handle, RTLD_DI_UNRESOLVED, &unresolved) == 0);
0103   if (has_unresolved)
0104   {
0105     if (unresolved == 0)
0106     {
0107       dl_load_dump();
0108       rtems_test_assert (unresolved != 0);
0109     }
0110   }
0111   else
0112   {
0113     if (unresolved != 0)
0114     {
0115       dl_load_dump();
0116       rtems_test_assert (unresolved == 0);
0117     }
0118   }
0119   if (handle == RTLD_SELF)
0120     printf ("handle: RTL_SELF: %sunresolved externals\n",
0121             unresolved != 0 ? "" : "no ");
0122   else
0123     printf ("handle: %p: %sunresolved externals\n",
0124             handle, unresolved != 0 ? "" : "no ");
0125 }
0126 
0127 static void* dl_load_obj (const char* name, bool has_unresolved)
0128 {
0129   void* handle;
0130 
0131   printf("load: %s\n", name);
0132 
0133   handle = dlopen (name, RTLD_NOW | RTLD_GLOBAL);
0134   if (!handle)
0135   {
0136     printf("dlopen failed: %s\n", dlerror());
0137     return NULL;
0138   }
0139 
0140   dl_check_resolved (handle, has_unresolved);
0141 
0142   printf ("handle: %p loaded\n", handle);
0143 
0144   return handle;
0145 }
0146 
0147 static void dl_close (void* handle)
0148 {
0149   int r;
0150   printf ("handle: %p closing\n", handle);
0151   r = dlclose (handle);
0152   if (r != 0)
0153     printf("dlclose failed: %s\n", dlerror());
0154   rtems_test_assert (r == 0);
0155 }
0156 
0157 static int dl_call (void* handle, const char* func)
0158 {
0159   static call_sig last_call;
0160   call_sig call = dlsym (handle, func);
0161   if (call == NULL)
0162   {
0163     printf("dlsym failed: symbol not found: %s\n", func);
0164     return 1;
0165   }
0166   if (last_call != NULL && last_call != call)
0167   {
0168     printf("Call location different: moved by: %i (call:%p last:%p)\n",
0169            (int) (call - last_call),
0170            call, last_call);
0171   }
0172   last_call = call;
0173   call ();
0174   return 0;
0175 }
0176 
0177 static void dl_object_open (object_def* od, objects* o)
0178 {
0179   o->handle = dl_load_obj(od->name, od->has_unresolved);
0180   rtems_test_assert (o->handle != NULL);
0181   if (!od->has_unresolved)
0182     dl_check_resolved (o->handle, false);
0183   if (od->space != 0)
0184   {
0185     o->space = malloc (od->space);
0186     printf("space alloc: %s: %zd: %p\n", od->name, od->space, o->space);
0187     rtems_test_assert (o->space != NULL);
0188   }
0189   dl_load_dump ();
0190 }
0191 
0192 static void dl_object_close (objects* o)
0193 {
0194   dl_close (o->handle);
0195   printf("space dealloc: %p\n", o->space);
0196   free (o->space);
0197 }
0198 
0199 /*
0200  * Private architecture back end call.
0201  */
0202 extern size_t rtems_rtl_elf_relocate_tramp_max_size (void);
0203 static size_t dl_alloc_size (void)
0204 {
0205   /*
0206    * If the max tramp size is 0 there is no tramp support, so
0207    * return 0.
0208    */
0209   if (rtems_rtl_elf_relocate_tramp_max_size () == 0)
0210     return 0;
0211   return MBYTES(32);
0212 }
0213 
0214 int dl_load_test(void)
0215 {
0216   object_def od[5] = { { "/dl09-o1.o", true,  dl_alloc_size () },
0217                        { "/dl09-o2.o", true,  dl_alloc_size () },
0218                        { "/dl09-o3.o", true,  dl_alloc_size () },
0219                        { "/dl09-o4.o", true,  dl_alloc_size () },
0220                        { "/dl09-o5.o", false, 0          } };
0221   objects o[5] = { 0 };
0222   size_t  i;
0223 
0224   printf ("Test source (link in strstr): %s\n", dl_localise_file (__FILE__));
0225   printf ("Allocation size: %zu\n", dl_alloc_size ());
0226 
0227 #if DL09_DEBUG_TRACE
0228   rtems_rtl_trace_set_mask (DL09_DEBUG_TRACE);
0229 #endif
0230 
0231   for (i = 0; i < NUMOF(od); ++i)
0232     dl_object_open (&od[i], &o[i]);
0233 
0234   dl_load_dump ();
0235 
0236   /*
0237    * Check for any resolved externals.
0238    */
0239   printf ("Check is any unresolved externals exist:\n");
0240   dl_check_resolved (RTLD_SELF, false);
0241 
0242   printf ("Running rtems_main_o1:\n");
0243   if (dl_call (o[0].handle, "rtems_main_o1"))
0244     return 1;
0245 
0246   for (i = 0; i < NUMOF (od); ++i)
0247     dl_object_close (&o[i]);
0248 
0249   return 0;
0250 }