2 * BinReloc - a library for creating relocatable executables
3 * Written by: Mike Hearn <mike@theoretic.com>
4 * Hongli Lai <h.lai@chello.nl>
5 * http://autopackage.org/
7 * This source code is public domain. You can relicense this code
8 * under whatever license you want.
10 * NOTE: if you're using C++ and are getting "undefined reference
11 * to br_*", try renaming prefix.c to prefix.cpp
21 * enrico - all the code below is only compiled and used if ENABLE_BINRELOC is set in config.h,
22 * this only happens if configure option --enable-binreloc was used
24 #ifdef ENABLE_BINRELOC
37 #define NULL ((void *) 0)
40 #define br_return_val_if_fail(expr,val) if (!(expr)) {fprintf (stderr, "** BinReloc (%s): assertion %s failed\n", __PRETTY_FUNCTION__, #expr); return val;}
42 #define br_return_val_if_fail(expr, val) if (!(expr)) return val
46 #include <sys/types.h>
48 #include <sys/param.h>
52 static char *br_last_value
= (char*)NULL
;
64 * br_thread_local_store:
65 * str: A dynamically allocated string.
66 * Returns: str. This return value must not be freed.
68 * Store str in a thread-local variable and return str. The next
69 * you run this function, that variable is freed too.
70 * This function is created so you don't have to worry about freeing
75 * foo = thread_local_store (strdup ("hello")); --> foo == "hello"
76 * foo = thread_local_store (strdup ("world")); --> foo == "world"; "hello" is now freed.
79 br_thread_local_store (char *str
)
81 static int initialized
= 0;
86 atexit (br_free_last_value
);
94 return (const char *) str
;
100 * symbol: A symbol that belongs to the app/library you want to locate.
101 * Returns: A newly allocated string containing the full path of the
102 * app/library that func belongs to, or NULL on error. This
103 * string should be freed when not when no longer needed.
105 * Finds out to which application or library symbol belongs, then locate
106 * the full path of that application or library.
107 * Note that symbol cannot be a pointer to a function. That will not work.
111 * #include "prefix.h"
112 * #include "libfoo.h"
114 * int main (int argc, char *argv[]) {
115 * printf ("Full path of this app: %s\n", br_locate (&argc));
120 * --> libfoo.c starts here
121 * #include "prefix.h"
123 * void libfoo_start () {
124 * --> "" is a symbol that belongs to libfoo (because it's called
125 * --> from libfoo_start()); that's why this works.
126 * printf ("libfoo is located in: %s\n", br_locate (""));
130 br_locate (void *symbol
)
136 br_return_val_if_fail (symbol
!= NULL
, NULL
);
138 f
= fopen ("/proc/self/maps", "r");
144 unsigned long start
, end
;
146 if (!fgets (line
, sizeof (line
), f
))
148 if (!strstr (line
, " r-xp ") || !strchr (line
, '/'))
151 sscanf (line
, "%lx-%lx ", &start
, &end
);
152 if (symbol
>= (void *) start
&& symbol
< (void *) end
)
157 /* Extract the filename; it is always an absolute path */
158 path
= strchr (line
, '/');
160 /* Get rid of the newline */
161 tmp
= strrchr (path
, '\n');
164 /* Get rid of "(deleted)" */
166 if (len
> 10 && strcmp (path
+ len
- 10, " (deleted)") == 0)
168 tmp
= path
+ len
- 10;
173 return strdup (path
);
184 * path: The full path of an executable or library.
185 * Returns: The prefix, or NULL on error. This string should be freed when no longer needed.
187 * Extracts the prefix from path. This function assumes that your executable
188 * or library is installed in an LSB-compatible directory structure.
191 * br_extract_prefix ("/usr/bin/gnome-panel"); --> Returns "/usr"
192 * br_extract_prefix ("/usr/local/lib/libfoo.so"); --> Returns "/usr/local"
193 * br_extract_prefix ("/usr/local/libfoo.so"); --> Returns "/usr"
196 br_extract_prefix (const char *path
)
198 char *end
, *tmp
, *result
;
200 br_return_val_if_fail (path
!= (char*)NULL
, (char*)NULL
);
202 if (!*path
) return strdup ("/");
203 end
= strrchr (path
, '/');
204 if (!end
) return strdup (path
);
206 tmp
= g_strndup ((char *) path
, end
- path
);
212 end
= strrchr (tmp
, '/');
213 if (!end
) return tmp
;
215 result
= g_strndup (tmp
, end
- tmp
);
221 result
= strdup ("/");
230 * symbol: A symbol that belongs to the app/library you want to locate.
231 * Returns: A prefix. This string should be freed when no longer needed.
233 * Locates the full path of the app/library that symbol belongs to, and return
234 * the prefix of that path, or NULL on error.
235 * Note that symbol cannot be a pointer to a function. That will not work.
238 * --> This application is located in /usr/bin/foo
239 * br_locate_prefix (&argc); --> returns: "/usr"
242 br_locate_prefix (void *symbol
)
246 br_return_val_if_fail (symbol
!= NULL
, NULL
);
248 path
= br_locate (symbol
);
249 if (!path
) return NULL
;
251 prefix
= br_extract_prefix (path
);
259 * symbol: A symbol that belongs to the app/library you want to locate.
260 * path: The path that you want to prepend the prefix to.
261 * Returns: The new path, or NULL on error. This string should be freed when no
264 * Gets the prefix of the app/library that symbol belongs to. Prepend that prefix to path.
265 * Note that symbol cannot be a pointer to a function. That will not work.
268 * --> The application is /usr/bin/foo
269 * br_prepend_prefix (&argc, "/share/foo/data.png"); --> Returns "/usr/share/foo/data.png"
272 br_prepend_prefix (void *symbol
, char *path
)
276 br_return_val_if_fail (symbol
!= NULL
, NULL
);
277 br_return_val_if_fail (path
!= NULL
, NULL
);
279 tmp
= br_locate_prefix (symbol
);
280 if (!tmp
) return NULL
;
282 if (strcmp (tmp
, "/") == 0)
283 newpath
= strdup (path
);
285 newpath
= g_strconcat (tmp
, path
, NULL
);
292 #else /* ENABLE_BINRELOC */
294 typedef int iso_c_forbids_an_empty_source_file
;
296 #endif /* ENABLE_BINRELOC */