Code::Blocks  SVN r11506
prefix.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
3  * http://www.gnu.org/licenses/gpl-3.0.html
4  *
5  * $Revision: 5613 $
6  * $Id: prefix.cpp 5613 2009-05-30 16:45:25Z killerbot $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/src/src/prefix.cpp $
8  */
9 
10 /*
11  * BinReloc - a library for creating relocatable executables
12  * Written by: Mike Hearn <mike@theoretic.com>
13  * Hongli Lai <h.lai@chello.nl>
14  * http://autopackage.org/
15  *
16  * This source code is public domain. You can relicense this code
17  * under whatever license you want.
18  *
19  * NOTE: if you're using C++ and are getting "undefined reference
20  * to br_*", try renaming prefix.c to prefix.cpp
21  */
22 
23 /* WARNING, BEFORE YOU MODIFY PREFIX.C:
24  *
25  * If you make changes to any of the functions in prefix.c, you MUST
26  * change the BR_NAMESPACE macro (in prefix.h).
27  * This way you can avoid symbol table conflicts with other libraries
28  * that also happen to use BinReloc.
29  *
30  * Example:
31  * #define BR_NAMESPACE(funcName) foobar_ ## funcName
32  * --> expands br_locate to foobar_br_locate
33  */
34 
35 #ifndef _PREFIX_C_
36 #define _PREFIX_C_
37 
38 #ifdef HAVE_CONFIG_H
39  #include "config.h"
40 #endif
41 
42 #ifndef BR_PTHREADS
43  /* Change 1 to 0 if you don't want pthread support */
44  #define BR_PTHREADS 1
45 #endif /* BR_PTHREADS */
46 
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include <limits.h>
50 #include <string.h>
51 #include "prefix.h"
52 
53 #ifdef __cplusplus
54 extern "C" {
55 #endif /* __cplusplus */
56 
57 
58 #undef NULL
59 #define NULL ((void *) 0)
60 
61 #ifdef __GNUC__
62  #define br_return_val_if_fail(expr,val) if (!(expr)) {fprintf (stderr, "** BinReloc (%s): assertion %s failed\n", __PRETTY_FUNCTION__, #expr); return val;}
63 #else
64  #define br_return_val_if_fail(expr,val) if (!(expr)) return val
65 #endif /* __GNUC__ */
66 
67 
68 #ifdef ENABLE_BINRELOC
69 #include <sys/types.h>
70 #include <sys/stat.h>
71 #include <sys/param.h>
72 #include <unistd.h>
73 
74 
106 char *
107 br_locate (void *symbol)
108 {
109  char line[5000];
110  FILE *f;
111  char *path;
112 
113  br_return_val_if_fail (symbol != NULL, (char*)NULL);
114 
115  f = fopen ("/proc/self/maps", "r");
116  if (!f)
117  return (char*)NULL;
118 
119  while (!feof (f))
120  {
121  unsigned long start, end;
122 
123  if (!fgets (line, sizeof (line), f))
124  continue;
125  if (!strstr (line, " r-xp ") || !strchr (line, '/'))
126  continue;
127 
128  sscanf (line, "%lx-%lx ", &start, &end);
129  if (symbol >= (void *) start && symbol < (void *) end)
130  {
131  char *tmp;
132  size_t len;
133 
134  /* Extract the filename; it is always an absolute path */
135  path = strchr (line, '/');
136 
137  /* Get rid of the newline */
138  tmp = strrchr (path, '\n');
139  if (tmp) *tmp = 0;
140 
141  /* Get rid of "(deleted)" */
142  len = strlen (path);
143  if (len > 10 && strcmp (path + len - 10, " (deleted)") == 0)
144  {
145  tmp = path + len - 10;
146  *tmp = 0;
147  }
148 
149  fclose(f);
150  return strdup (path);
151  }
152  }
153 
154  fclose (f);
155  return (char*)NULL;
156 }
157 
158 
172 char *
173 br_locate_prefix (void *symbol)
174 {
175  char *path, *prefix;
176 
177  br_return_val_if_fail (symbol != NULL, (char*)NULL);
178 
179  path = br_locate (symbol);
180  if (!path) return (char*)NULL;
181 
182  prefix = br_extract_prefix (path);
183  free (path);
184  return prefix;
185 }
186 
187 
202 char *
203 br_prepend_prefix (void *symbol, char *path)
204 {
205  br_return_val_if_fail (symbol != 0, (char*)0);
206  br_return_val_if_fail (path != 0, (char*)0);
207 
208  char* tmp = br_locate_prefix (symbol);
209  if (!tmp) return (char*)0;
210 
211  char *newpath;
212  if (strcmp (tmp, "/") == 0)
213  newpath = strdup (path);
214  else
215  newpath = br_strcat (tmp, path);
216 
217  /* Get rid of compiler warning ("br_prepend_prefix never used") */
218  if (0) br_prepend_prefix (0, (char*)0);
219 
220  free (tmp);
221  return newpath;
222 }
223 
224 #endif /* ENABLE_BINRELOC */
225 
226 
227 /* Pthread stuff for thread safetiness */
228 #if BR_PTHREADS
229 
230 #include <pthread.h>
231 
232 static pthread_key_t br_thread_key;
233 #ifdef __FreeBSD__
234 static pthread_once_t br_thread_key_once = {0, (pthread_mutex_t)NULL};//PTHREAD_ONCE_INIT;
235 #else
236 static pthread_once_t br_thread_key_once = PTHREAD_ONCE_INIT;
237 #endif
238 
239 static void
241 {
242  char* specific = (char *) pthread_getspecific (br_thread_key);
243  if (specific)
244  {
245  free (specific);
246  pthread_setspecific (br_thread_key, NULL);
247  }
248  pthread_key_delete (br_thread_key);
249  br_thread_key = 0;
250 }
251 
252 
253 static void
254 br_str_free (void *str)
255 {
256  if (str)
257  free (str);
258 }
259 
260 
261 static void
263 {
264  if (pthread_key_create (&br_thread_key, br_str_free) == 0)
266 }
267 
268 #else /* BR_PTHREADS */
269 
270 static char *br_last_value = (char *) NULL;
271 
272 static void
273 br_free_last_value ()
274 {
275  if (br_last_value)
276  free (br_last_value);
277 }
278 
279 #endif /* BR_PTHREADS */
280 
281 
297 const char *
299 {
300  #if BR_PTHREADS
301  pthread_once (&br_thread_key_once, br_thread_local_store_init);
302 
303  char* specific = (char *) pthread_getspecific (br_thread_key);
304  br_str_free (specific);
305  pthread_setspecific (br_thread_key, str);
306 
307  #else /* BR_PTHREADS */
308  static int initialized = 0;
309 
310  if (!initialized)
311  {
312  atexit (br_free_last_value);
313  initialized = 1;
314  }
315 
316  if (br_last_value)
317  free (br_last_value);
318  br_last_value = str;
319  #endif /* BR_PTHREADS */
320 
321  return (const char *) str;
322 }
323 
324 
333 char *
334 br_strcat (const char *str1, const char *str2)
335 {
336  if (!str1) str1 = "";
337  if (!str2) str2 = "";
338 
339  size_t len1 = strlen (str1);
340  size_t len2 = strlen (str2);
341 
342  char* result = (char *) malloc (len1 + len2 + 1);
343  memcpy (result, str1, len1);
344  memcpy (result + len1, str2, len2);
345  result[len1 + len2] = '\0';
346 
347  return result;
348 }
349 
350 
351 /* Emulates glibc's strndup() */
352 static char *
353 br_strndup (char *str, size_t size)
354 {
355  br_return_val_if_fail (str != (char *) 0, (char *) 0);
356 
357  size_t len = strlen (str);
358  if (!len) return strdup ("");
359  if (size > len) size = len;
360 
361  char* result = (char *) calloc (sizeof (char), len + 1);
362  memcpy (result, str, size);
363  return result;
364 }
365 
366 
378 char *
379 br_extract_dir (const char *path)
380 {
381  br_return_val_if_fail (path != (char *) 0, (char *) 0);
382 
383  const char* end = strrchr (path, '/');
384  if (!end) return strdup (".");
385 
386  while (end > path && *end == '/')
387  {
388  end--;
389  }
390  char* result = br_strndup ((char *) path, end - path + 1);
391  if (!*result)
392  {
393  free (result);
394  return strdup ("/");
395  } else
396  return result;
397 }
398 
399 
413 char *
414 br_extract_prefix (const char *path)
415 {
416  br_return_val_if_fail (path != (char *) 0, (char *) 0);
417 
418  if (!*path) return strdup ("/");
419  const char* end = strrchr (path, '/');
420  if (!end) return strdup (path);
421 
422  char* tmp = br_strndup ((char *) path, end - path);
423  if (!*tmp)
424  {
425  free (tmp);
426  return strdup ("/");
427  }
428  end = strrchr (tmp, '/');
429  if (!end) return tmp;
430 
431  char* result = br_strndup (tmp, end - tmp);
432  free (tmp);
433 
434  if (!*result)
435  {
436  free (result);
437  result = strdup ("/");
438  }
439 
440  return result;
441 }
442 
443 
444 #ifdef __cplusplus
445 }
446 #endif /* __cplusplus */
447 
448 #endif /* _PREFIX_C */
static pthread_once_t br_thread_key_once
Definition: prefix.cpp:236
static pthread_key_t br_thread_key
Definition: prefix.cpp:232
#define br_return_val_if_fail(expr, val)
Definition: prefix.cpp:64
char * br_extract_dir(const char *path)
br_extract_dir: path: A path.
Definition: prefix.cpp:379
static void br_thread_local_store_init()
Definition: prefix.cpp:262
char * br_extract_prefix(const char *path)
br_extract_prefix: path: The full path of an executable or library.
Definition: prefix.cpp:414
static void br_thread_local_store_fini()
Definition: prefix.cpp:240
static void br_str_free(void *str)
Definition: prefix.cpp:254
static char * br_strndup(char *str, size_t size)
Definition: prefix.cpp:353
char * br_strcat(const char *str1, const char *str2)
br_strcat: str1: A string.
Definition: prefix.cpp:334
const char * br_thread_local_store(char *str)
br_thread_local_store: str: A dynamically allocated string.
Definition: prefix.cpp:298
#define NULL
Definition: prefix.cpp:59