#include <stddef.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <fcntl.h>
#include <limits.h>
#include <libelf.h>
#define PATH_MAX 1024
#endif
+/*
+ * Work with older glibc: stub out O_PATH if not available. (We can work
+ * without it.)
+ */
+#ifndef O_PATH
+# define O_PATH 0
+#endif
+
#ifndef __GNUC__
#define __attribute__((foo))
#endif
/*
* Populate the member blacklist from the member_blacklist file.
*/
-static void init_member_blacklist(const char *member_blacklist_file);
+static void init_member_blacklist(const char *member_blacklist_file,
+ const char *srcdir);
/*
* Return 1 if a given DWARF DIE, which must be a DW_TAG_member, appears in the
*/
static const char *abs_file_name(const char *file_name);
+/*
+ * Determine absolute filenames relative to some other directory: do not cache
+ * them. It is the caller's responsibility to free them.
+ */
+static char *rel_abs_file_name(const char *file_name, const char *relative_to);
+
/*
* Trivial wrapper, avoid an incompatible pointer type warning.
*/
trace = getenv("DWARF2CTF_TRACE");
- if ((argc != 4 && argc != 7) ||
+ if ((argc != 4 && argc != 8) ||
(argc == 4 && strcmp(argv[2], "-e") != 0)) {
- fprintf(stderr, "Syntax: dwarf2ctf outputdir objects.builtin modules.builtin dedup.blacklist\n");
+ fprintf(stderr, "Syntax: dwarf2ctf outputdir srcdir "
+ "objects.builtin modules.builtin dedup.blacklist\n");
fprintf(stderr, " member.blacklist filelist\n");
- fprintf(stderr, " or dwarf2ctf outputdir -e filelist"
+ fprintf(stderr, " or dwarf2ctf outputdir -e filelist\n"
"for external module use\n");
exit(1);
}
* independently invoked with every argument.
*/
if (strcmp(argv[2], "-e") != 0) {
+ const char *srcdir;
char *builtin_objects_file;
char *builtin_module_file;
char *dedup_blacklist_file;
char *member_blacklist_file;
- builtin_objects_file = argv[2];
- builtin_module_file = argv[3];
- dedup_blacklist_file = argv[4];
- member_blacklist_file = argv[5];
+ srcdir = argv[2];
+ builtin_objects_file = argv[3];
+ builtin_module_file = argv[4];
+ dedup_blacklist_file = argv[5];
+ member_blacklist_file = argv[6];
init_builtin(builtin_objects_file, builtin_module_file);
init_dedup_blacklist(dedup_blacklist_file);
- init_member_blacklist(member_blacklist_file);
- init_object_names(argv[6]);
+ init_member_blacklist(member_blacklist_file, srcdir);
+ init_object_names(argv[7]);
run(output_dir);
} else {
/*
* Populate the member blacklist from the member_blacklist file.
*/
-static void init_member_blacklist(const char *member_blacklist_file)
+static void init_member_blacklist(const char *member_blacklist_file,
+ const char *srcdir)
{
FILE *f;
char *line = NULL;
*last_colon = '\0';
last_colon++;
- absolutized = xstrdup(abs_file_name(line));
+ absolutized = rel_abs_file_name(line, srcdir);
absolutized = str_appendn(absolutized, ":", last_colon, NULL);
g_hash_table_insert(member_blacklist, absolutized, NULL);
return abs_name;
}
+/*
+ * Determine absolute filenames relative to some other directory. This does not
+ * need to be fast. The returned name is dynamically allocated, and must be
+ * freed by the caller.
+ */
+static char *rel_abs_file_name(const char *file_name, const char *relative_to)
+{
+ int dir = -1;
+ static int warned = 0;
+ char *abspath;
+ /*
+ * If we can't get this name relatively, we might as well *try* to do it
+ * absolutely: but print a warning.
+ */
+ if ((dir = open(".", O_RDONLY | O_DIRECTORY | O_PATH)) < 0) {
+ if (!warned) {
+ fprintf(stderr, "Cannot open current directory: %s\n",
+ strerror(errno));
+ warned = 1;
+ }
+ } else {
+ if (chdir(relative_to) < 0)
+ if (!warned) {
+ fprintf(stderr, "Cannot change "
+ "directory to %s: %s\n",
+ relative_to, strerror(errno));
+ warned = 1;
+ }
+ }
+
+ abspath = realpath(file_name, NULL);
+ if (abspath == NULL)
+ abspath = strdup(file_name);
+
+ if ((dir > -1) && (fchdir(dir) < 0)) {
+ fprintf(stderr, "Cannot return to original directory "
+ "after relative realpath(): %s\n",
+ strerror(errno));
+ exit(1);
+ }
+
+ return abspath;
+}
+
/*
* Given a type encoding table, and a size, return the CTF encoding for that
* type, or 0 if none.