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
19 * enrico - all the code below is only compiled and used if ENABLE_BINRELOC is set in config.h,
20 * this only happens if configure option --enable-binreloc was used
22 #ifdef ENABLE_BINRELOC
35 #define NULL ((void *) 0)
38 #define br_return_val_if_fail(expr,val) if (!(expr)) {fprintf (stderr, "** BinReloc (%s): assertion %s failed\n", __PRETTY_FUNCTION__, #expr); return val;}
40 #define br_return_val_if_fail(expr, val) if (!(expr)) return val
44 #include <sys/types.h>
46 #include <sys/param.h>
50 static char *br_last_value
= (char*)NULL
;
54 br_free_last_value (void)
62 * br_thread_local_store:
63 * str: A dynamically allocated string.
64 * Returns: str. This return value must not be freed.
66 * Store str in a thread-local variable and return str. The next
67 * you run this function, that variable is freed too.
68 * This function is created so you don't have to worry about freeing
73 * foo = thread_local_store (strdup ("hello")); --> foo == "hello"
74 * foo = thread_local_store (strdup ("world")); --> foo == "world"; "hello" is now freed.
77 br_thread_local_store (char *str
)
79 static int initialized
= 0;
84 atexit (br_free_last_value
);
92 return (const char *) str
;
98 * symbol: A symbol that belongs to the app/library you want to locate.
99 * Returns: A newly allocated string containing the full path of the
100 * app/library that func belongs to, or NULL on error. This
101 * string should be freed when not when no longer needed.
103 * Finds out to which application or library symbol belongs, then locate
104 * the full path of that application or library.
105 * Note that symbol cannot be a pointer to a function. That will not work.
109 * #include "prefix.h"
110 * #include "libfoo.h"
112 * int main (int argc, char *argv[]) {
113 * printf ("Full path of this app: %s\n", br_locate (&argc));
118 * --> libfoo.c starts here
119 * #include "prefix.h"
121 * void libfoo_start () {
122 * --> "" is a symbol that belongs to libfoo (because it's called
123 * --> from libfoo_start()); that's why this works.
124 * printf ("libfoo is located in: %s\n", br_locate (""));
128 br_locate (void *symbol
)
134 br_return_val_if_fail (symbol
!= NULL
, NULL
);
136 f
= fopen ("/proc/self/maps", "r");
142 unsigned long start
, end
;
144 if (!fgets (line
, sizeof (line
), f
))
146 if (!strstr (line
, " r-xp ") || !strchr (line
, '/'))
149 sscanf (line
, "%lx-%lx ", &start
, &end
);
150 if (symbol
>= (void *) start
&& symbol
< (void *) end
)
155 /* Extract the filename; it is always an absolute path */
156 path
= strchr (line
, '/');
158 /* Get rid of the newline */
159 tmp
= strrchr (path
, '\n');
162 /* Get rid of "(deleted)" */
164 if (len
> 10 && strcmp (path
+ len
- 10, " (deleted)") == 0)
166 tmp
= path
+ len
- 10;
171 return strdup (path
);
182 * path: The full path of an executable or library.
183 * Returns: The prefix, or NULL on error. This string should be freed when no longer needed.
185 * Extracts the prefix from path. This function assumes that your executable
186 * or library is installed in an LSB-compatible directory structure.
189 * br_extract_prefix ("/usr/bin/gnome-panel"); --> Returns "/usr"
190 * br_extract_prefix ("/usr/local/lib/libfoo.so"); --> Returns "/usr/local"
191 * br_extract_prefix ("/usr/local/libfoo.so"); --> Returns "/usr"
194 br_extract_prefix (const char *path
)
196 char *end
, *tmp
, *result
;
198 br_return_val_if_fail (path
!= (char*)NULL
, (char*)NULL
);
200 if (!*path
) return strdup ("/");
201 end
= strrchr (path
, '/');
202 if (!end
) return strdup (path
);
204 tmp
= g_strndup ((char *) path
, end
- path
);
210 end
= strrchr (tmp
, '/');
211 if (!end
) return tmp
;
213 result
= g_strndup (tmp
, end
- tmp
);
219 result
= strdup ("/");
228 * symbol: A symbol that belongs to the app/library you want to locate.
229 * Returns: A prefix. This string should be freed when no longer needed.
231 * Locates the full path of the app/library that symbol belongs to, and return
232 * the prefix of that path, or NULL on error.
233 * Note that symbol cannot be a pointer to a function. That will not work.
236 * --> This application is located in /usr/bin/foo
237 * br_locate_prefix (&argc); --> returns: "/usr"
240 br_locate_prefix (void *symbol
)
244 br_return_val_if_fail (symbol
!= NULL
, NULL
);
246 path
= br_locate (symbol
);
247 if (!path
) return NULL
;
249 prefix
= br_extract_prefix (path
);
257 * symbol: A symbol that belongs to the app/library you want to locate.
258 * path: The path that you want to prepend the prefix to.
259 * Returns: The new path, or NULL on error. This string should be freed when no
262 * Gets the prefix of the app/library that symbol belongs to. Prepend that prefix to path.
263 * Note that symbol cannot be a pointer to a function. That will not work.
266 * --> The application is /usr/bin/foo
267 * br_prepend_prefix (&argc, "/share/foo/data.png"); --> Returns "/usr/share/foo/data.png"
270 br_prepend_prefix (void *symbol
, char *path
)
274 br_return_val_if_fail (symbol
!= NULL
, NULL
);
275 br_return_val_if_fail (path
!= NULL
, NULL
);
277 tmp
= br_locate_prefix (symbol
);
278 if (!tmp
) return NULL
;
280 if (strcmp (tmp
, "/") == 0)
281 newpath
= strdup (path
);
283 newpath
= g_strconcat (tmp
, path
, NULL
);
290 #else /* ENABLE_BINRELOC */
292 typedef int iso_c_forbids_an_empty_source_file
;
294 #endif /* ENABLE_BINRELOC */