ns-3 Direct Code Execution
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
libc.cc
Go to the documentation of this file.
1 
2 #include "libc.h"
3 
4 struct Libc g_libc;
5 
6 // macros stolen from glibc.
7 #define weak_alias(name, aliasname) \
8  extern __typeof (name) aliasname __attribute__ ((weak, alias (# name)))
9 
10 extern "C" {
11 
12 // Step 2. Very dirty trick to force redirection to library functions
13 // This will work only with GCC. Number 128 was picked to be arbitrarily large to allow
14 // function calls with a large number of arguments.
15 // \see http://tigcc.ticalc.org/doc/gnuexts.html#SEC67___builtin_apply_args
16 // FIXME: 120925: 128 was heuristically picked to pass the test under 32bits environment.
17 #define NATIVE DCE
18 #define NATIVET DCET
19 #define NATIVE_WITH_ALIAS DCE_WITH_ALIAS
20 #define NATIVE_WITH_ALIAS2 DCE_WITH_ALIAS2
21 
22 #define GCC_BUILTIN_APPLY(export_symbol, func_to_call) \
23  void export_symbol (...) { \
24  void *args = __builtin_apply_args (); \
25  void *result = __builtin_apply (g_libc.func_to_call ## _fn, args, 128); \
26  __builtin_return (result); \
27  }
28 
29 #define GCC_BUILTIN_APPLYT(rtype, export_symbol, func_to_call) \
30  rtype export_symbol (...) { \
31  void *args = __builtin_apply_args (); \
32  void *result = __builtin_apply ((void (*) (...)) g_libc.func_to_call ## _fn, args, 128); \
33  __builtin_return (result); \
34  }
35 
36 
37 #define DCE(name) \
38  GCC_BUILTIN_APPLY (name,name)
39 
40 #define DCET(rtype,name) \
41  GCC_BUILTIN_APPLYT (rtype,name,name)
42 
43 /* From gcc/testsuite/gcc.dg/cpp/vararg2.c */
44 /* C99 __VA_ARGS__ versions */
45 #define c99_count(...) _c99_count1 (, ## __VA_ARGS__) /* If only ## worked.*/
46 #define _c99_count1(...) _c99_count2 (__VA_ARGS__,10,9,8,7,6,5,4,3,2,1,0)
47 #define _c99_count2(_,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,n,...) n
48 
49 #define FULL_ARGS_0()
50 #define FULL_ARGS_1(X0) X0 a0
51 #define FULL_ARGS_2(X0,X1) X0 a0, X1 a1
52 #define FULL_ARGS_3(X0,X1,X2) X0 a0, X1 a1, X2 a2
53 #define FULL_ARGS_4(X0,X1,X2,X3) X0 a0, X1 a1, X2 a2, X3 a3
54 #define FULL_ARGS_5(X0,X1,X2,X3,X4) X0 a0, X1 a1, X2 a2, X3 a3, X4 a4
55 
56 #define _ARGS_0()
57 #define _ARGS_1(X0) a0
58 #define _ARGS_2(X0,X1) a0, a1
59 #define _ARGS_3(X0,X1,X2) a0, a1, a2
60 #define _ARGS_4(X0,X1,X2,X3) a0, a1, a2, a3
61 #define _ARGS_5(X0,X1,X2,X3,X4) a0, a1, a2, a3, a4
62 
63 #define CAT(a, ...) PRIMITIVE_CAT (a, __VA_ARGS__)
64 #define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
65 
66 #define FULL_ARGS(...) CAT (FULL_ARGS_,c99_count (__VA_ARGS__)) (__VA_ARGS__)
67 #define ARGS(...) CAT (_ARGS_,c99_count (__VA_ARGS__)) (__VA_ARGS__)
68 
69 
70 #define DCE_EXPLICIT(name,rtype,...) \
71  rtype name (FULL_ARGS (__VA_ARGS__)) \
72  { \
73  return g_libc.name ## _fn (ARGS (__VA_ARGS__)); \
74  }
75 
76 #define DCE_WITH_ALIAS(name) \
77  GCC_BUILTIN_APPLY (__ ## name,name) \
78  weak_alias (__ ## name, name);
79 
80 #define DCE_WITH_ALIAS2(name, internal) \
81  GCC_BUILTIN_APPLY (internal,name) \
82  weak_alias (internal, name);
83 
84 
85 // Note: it looks like that the stdio.h header does
86 // not define putc and getc as macros if you include
87 // them from C++ so that we do need to define the putc
88 // and getc functions anyway.
89 #undef putc
90 #undef getc
91 
92 #include "libc-ns3.h" // do the work
93 
94 // weak_alias (strtol, __strtol_internal);
95 // weak_alias (wctype_l, __wctype_l);
96 // weak_alias (strdup, __strdup);
97 
98 // void exit(int status)
99 // {
100 // g_libc.exit_fn (status);
101 // int a = 0;
102 // while (1)
103 // {
104 // // loop forever to quiet compiler warning:
105 // // warning: ‘noreturn’ function does return
106 // a++;
107 // }
108 // }
109 
110 // void abort(void)
111 // {
112 // g_libc.abort_fn ();
113 // int a = 0;
114 // while (1)
115 // {
116 // // loop forever to quiet compiler warning:
117 // // warning: ‘noreturn’ function does return
118 // a++;
119 // }
120 // }
121 
122 char * strpbrk (const char *s, const char *a)
123 {
124  return g_libc.strpbrk_fn (s,a);
125 }
126 
127 char * strstr (const char *u, const char *d)
128 {
129  return g_libc.strstr_fn (u,d);
130 }
131 
132 int snprintf (char *s, size_t si, const char *f, ...)
133 {
134  va_list vl;
135  va_start (vl, f);
136  int r = g_libc.vsnprintf_fn (s, si, f, vl);
137  va_end (vl);
138 
139  return r;
140 }
141 int vsnprintf (char *s, size_t si, const char *f, va_list v)
142 {
143  return g_libc.vsnprintf_fn (s, si, f, v);
144 }
145 
146 #include "libc-globals.h"
147 
148 void LIBSETUP (const struct Libc *fn)
149 {
150  /* The following assignment of fn to g_libc is a bit weird: we perform a copy of the data
151  * structures by hand rather than executing g_libc = fn. This is obviously done on purpose.
152  * The reason is that g_libc = fn would trigger a call to the memcpy function because the
153  * Libc structure is very big. The memcpy function is resolved through the dynamic loader's
154  * symbol lookup mechanism to the local memcpy function and that local memcpy function happens
155  * to be calling g_libc.memcpy_fn which is set to NULL before the data structure is initialized.
156  */
157  const unsigned char *src = (const unsigned char *)fn;
158  unsigned char *dst = (unsigned char *)&g_libc;
159  unsigned int i;
160  for (i = 0; i < sizeof (struct Libc); ++i)
161  {
162  *dst = *src;
163  src++;
164  dst++;
165  }
166 
168 }
169 
170 #ifdef HAVE_GETCPUFEATURES
171 // Below there is an exception implementation: because the libm of glibc2.14 call __get_cpu_features during dlopen,
172 // and during dlopen of libm DCE do not have yet called lib_setup so there we implement __get_cpu_features
173 // directly without using the global g_libc variable, we can do it only if our implementation of the method
174 // do not interract with any ressouces of DCE or NS3 and do no call any other libc methods ...
175 struct cpu_features;
176 extern const struct cpu_features * dce___get_cpu_features (void);
177 const struct cpu_features * __get_cpu_features (void)
178 {
179  return dce___get_cpu_features ();
180 }
181 #endif
182 } // extern "C"