1 /* Standard find_debuginfo callback for libdwfl.
2 Copyright (C) 2005 Red Hat, Inc.
4 This program is Open Source software; you can redistribute it and/or
5 modify it under the terms of the Open Software License version 1.0 as
6 published by the Open Source Initiative.
8 You should have received a copy of the Open Software License along
9 with this program; if not, you may obtain a copy of the Open Software
10 License version 1.0 from http://www.opensource.org/licenses/osl.php or
11 by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
12 3001 King Ranch Road, Ukiah, CA 95482. */
21 #define DEFAULT_DEBUGINFO_PATH ":.debug:/usr/lib/debug"
24 /* Try to open64 [DIR/][SUBDIR/]DEBUGLINK, return file descriptor or -1.
25 On success, *DEBUGINFO_FILE_NAME has the malloc'd name of the open file. */
27 try_open (const char *dir, const char *subdir, const char *debuglink,
28 char **debuginfo_file_name)
31 if (dir == NULL && subdir == NULL)
32 fname = strdup (debuglink);
33 else if (subdir == NULL)
34 asprintf (&fname, "%s/%s", dir, debuglink);
36 asprintf (&fname, "%s/%s", subdir, debuglink);
38 asprintf (&fname, "%s/%s/%s", dir, subdir, debuglink);
43 int fd = open64 (fname, O_RDONLY);
47 *debuginfo_file_name = fname;
52 /* Return true iff the FD's contents CRC matches DEBUGLINK_CRC. */
54 check_crc (int fd, GElf_Word debuglink_crc)
57 return (__libdwfl_crc32_file (fd, &file_crc) == 0
58 && file_crc == debuglink_crc);
62 dwfl_standard_find_debuginfo (Dwfl_Module *mod __attribute__ ((unused)),
63 void **userdata __attribute__ ((unused)),
64 const char *modname __attribute__ ((unused)),
65 GElf_Addr base __attribute__ ((unused)),
66 const char *file_name,
67 const char *debuglink_file,
68 GElf_Word debuglink_crc,
69 char **debuginfo_file_name)
73 const char *file_basename = file_name == NULL ? NULL : basename (file_name);
74 if (debuglink_file == NULL)
76 if (file_basename == NULL)
82 size_t len = strlen (file_basename);
83 char *localname = alloca (len + sizeof ".debug");
84 memcpy (localname, file_basename, len);
85 memcpy (&localname[len], ".debug", sizeof ".debug");
86 debuglink_file = localname;
90 /* Look for a file named DEBUGLINK_FILE in the directories
91 indicated by the debug directory path setting. */
93 const Dwfl_Callbacks *const cb = mod->dwfl->callbacks;
94 char *path = strdupa ((cb->debuginfo_path ? *cb->debuginfo_path : NULL)
95 ?: DEFAULT_DEBUGINFO_PATH);
97 /* A leading - or + in the whole path sets whether to check file CRCs. */
99 if (path[0] == '-' || path[0] == '+')
101 defcheck = path[0] == '+';
105 char *file_dirname = (file_basename == file_name ? NULL
106 : strndupa (file_name, file_basename - 1 - file_name));
108 while ((p = strsep (&path, ":")) != NULL)
110 /* A leading - or + says whether to check file CRCs for this element. */
111 bool check = defcheck;
112 if (*p == '+' || *p == '-')
114 check = check && cancheck;
116 const char *dir, *subdir;
120 /* An empty entry says to try the main file's directory. */
125 /* An absolute path says to look there for a subdirectory
126 named by the main file's absolute directory.
127 This cannot be applied to a relative file name. */
128 if (file_dirname == NULL || file_dirname[0] != '/')
131 subdir = file_dirname + 1;
134 /* A relative path says to try a subdirectory of that name
135 in the main file's directory. */
142 int fd = try_open (dir, subdir, debuglink_file, &fname);
145 if (!check || check_crc (fd, debuglink_crc))
147 *debuginfo_file_name = fname;
158 INTDEF (dwfl_standard_find_debuginfo)