]>
Commit | Line | Data |
---|---|---|
ab050a48 BZ |
1 | http://sourceware.org/ml/gdb-patches/2009-10/msg00508.html |
2 | Subject: [patch 3/3] debug-file-directory with multiple components | |
3 | ||
4 | Hi, | |
5 | ||
6 | for various reasons `debug-file-directory' would be sometimes useful to have | |
7 | multiple components such as `solib-search-path' has. | |
8 | ||
9 | I found it useful myself during various separate debuginfo tests/scripts. | |
10 | ||
11 | It was requested for the ABRT bugreporting project at the preceding mail of: | |
12 | https://fedorahosted.org/pipermail/crash-catcher/2009-October/000054.html | |
13 | ||
14 | It should be a backward compatible extension as DIRNAME_SEPARATOR should never | |
15 | be a valid part of a single DEBUG_FILE_DIRECTORY component. | |
16 | ||
17 | ||
18 | Thanks, | |
19 | Jan | |
20 | ||
21 | ||
22 | gdb/doc/ | |
23 | 2009-10-22 Jan Kratochvil <jan.kratochvil@redhat.com> | |
24 | ||
25 | * gdb.texinfo (set debug-file-directory, show debug-file-directory) | |
26 | (Auto-loading): Use plural and note one can use multiple components now. | |
27 | ||
28 | gdb/ | |
29 | 2009-10-22 Jan Kratochvil <jan.kratochvil@redhat.com> | |
30 | ||
31 | * symfile.c (build_id_to_debug_filename): New variable debugdir. Move | |
32 | variables size, s and data into a new inner block. Change xmalloc for | |
33 | alloca, use direct BUILDID->SIZE there now. Loop for the | |
34 | DEBUG_FILE_DIRECTORY components. | |
35 | (find_separate_debug_file): New variable debugdir and debugdir_end. | |
36 | Loop for the DEBUG_FILE_DIRECTORY components. | |
37 | (_initialize_symfile): For "debug-file-directory" use plural and note | |
38 | one can use multiple components now. | |
39 | ||
40 | gdb/testsuite/ | |
41 | 2009-10-22 Jan Kratochvil <jan.kratochvil@redhat.com> | |
42 | ||
43 | * gdb.base/sepdebug.exp: New test_different_dir call for multiple-dirs. | |
44 | ||
45 | --- a/gdb/doc/gdb.texinfo | |
46 | +++ b/gdb/doc/gdb.texinfo | |
47 | @@ -14066,13 +14066,14 @@ name @value{GDBN} is currently using. | |
48 | @table @code | |
49 | ||
50 | @kindex set debug-file-directory | |
51 | -@item set debug-file-directory @var{directory} | |
52 | -Set the directory which @value{GDBN} searches for separate debugging | |
53 | -information files to @var{directory}. | |
54 | +@item set debug-file-directory @var{directories} | |
55 | +Set the directories which @value{GDBN} searches for separate debugging | |
56 | +information files to @var{directory}. Multiple directory components can be set | |
57 | +concatenating them by a directory separator. | |
58 | ||
59 | @kindex show debug-file-directory | |
60 | @item show debug-file-directory | |
61 | -Show the directory @value{GDBN} searches for separate debugging | |
62 | +Show the directories @value{GDBN} searches for separate debugging | |
63 | information files. | |
64 | ||
65 | @end table | |
66 | @@ -19336,8 +19337,8 @@ readable, @value{GDBN} will evaluate it as a Python script. | |
67 | ||
68 | If this file does not exist, and if the parameter | |
69 | @code{debug-file-directory} is set (@pxref{Separate Debug Files}), | |
70 | -then @value{GDBN} will use the file named | |
71 | -@file{@var{debug-file-directory}/@var{real-name}}, where | |
72 | +then @value{GDBN} will use for its each separated directory component | |
73 | +@code{component} the file named @file{@code{component}/@var{real-name}}, where | |
74 | @var{real-name} is the object file's real name, as described above. | |
75 | ||
76 | Finally, if this file does not exist, then @value{GDBN} will look for | |
77 | --- a/gdb/symfile.c | |
78 | +++ b/gdb/symfile.c | |
79 | @@ -1218,35 +1218,59 @@ build_id_verify (const char *filename, struct build_id *check) | |
80 | static char * | |
81 | build_id_to_debug_filename (struct build_id *build_id) | |
82 | { | |
83 | - char *link, *s, *retval = NULL; | |
84 | - gdb_byte *data = build_id->data; | |
85 | - size_t size = build_id->size; | |
86 | + char *link, *debugdir, *retval = NULL; | |
87 | ||
88 | /* DEBUG_FILE_DIRECTORY/.build-id/ab/cdef */ | |
89 | - link = xmalloc (strlen (debug_file_directory) + (sizeof "/.build-id/" - 1) + 1 | |
90 | - + 2 * size + (sizeof ".debug" - 1) + 1); | |
91 | - s = link + sprintf (link, "%s/.build-id/", debug_file_directory); | |
92 | - if (size > 0) | |
93 | - { | |
94 | - size--; | |
95 | - s += sprintf (s, "%02x", (unsigned) *data++); | |
96 | - } | |
97 | - if (size > 0) | |
98 | - *s++ = '/'; | |
99 | - while (size-- > 0) | |
100 | - s += sprintf (s, "%02x", (unsigned) *data++); | |
101 | - strcpy (s, ".debug"); | |
102 | - | |
103 | - /* lrealpath() is expensive even for the usually non-existent files. */ | |
104 | - if (access (link, F_OK) == 0) | |
105 | - retval = lrealpath (link); | |
106 | - xfree (link); | |
107 | - | |
108 | - if (retval != NULL && !build_id_verify (retval, build_id)) | |
109 | + link = alloca (strlen (debug_file_directory) + (sizeof "/.build-id/" - 1) + 1 | |
110 | + + 2 * build_id->size + (sizeof ".debug" - 1) + 1); | |
111 | + | |
112 | + /* Keep backward compatibility so that DEBUG_FILE_DIRECTORY being "" will | |
113 | + cause "/.build-id/..." lookups. */ | |
114 | + | |
115 | + debugdir = debug_file_directory; | |
116 | + do | |
117 | { | |
118 | - xfree (retval); | |
119 | - retval = NULL; | |
120 | + char *s, *debugdir_end; | |
121 | + gdb_byte *data = build_id->data; | |
122 | + size_t size = build_id->size; | |
123 | + | |
124 | + while (*debugdir == DIRNAME_SEPARATOR) | |
125 | + debugdir++; | |
126 | + | |
127 | + debugdir_end = strchr (debugdir, DIRNAME_SEPARATOR); | |
128 | + if (debugdir_end == NULL) | |
129 | + debugdir_end = &debugdir[strlen (debugdir)]; | |
130 | + | |
131 | + memcpy (link, debugdir, debugdir_end - debugdir); | |
132 | + s = &link[debugdir_end - debugdir]; | |
133 | + s += sprintf (s, "/.build-id/"); | |
134 | + if (size > 0) | |
135 | + { | |
136 | + size--; | |
137 | + s += sprintf (s, "%02x", (unsigned) *data++); | |
138 | + } | |
139 | + if (size > 0) | |
140 | + *s++ = '/'; | |
141 | + while (size-- > 0) | |
142 | + s += sprintf (s, "%02x", (unsigned) *data++); | |
143 | + strcpy (s, ".debug"); | |
144 | + | |
145 | + /* lrealpath() is expensive even for the usually non-existent files. */ | |
146 | + if (access (link, F_OK) == 0) | |
147 | + retval = lrealpath (link); | |
148 | + | |
149 | + if (retval != NULL && !build_id_verify (retval, build_id)) | |
150 | + { | |
151 | + xfree (retval); | |
152 | + retval = NULL; | |
153 | + } | |
154 | + | |
155 | + if (retval != NULL) | |
156 | + break; | |
157 | + | |
158 | + debugdir = debugdir_end; | |
159 | } | |
160 | + while (*debugdir != 0); | |
161 | ||
162 | return retval; | |
163 | } | |
164 | @@ -1333,7 +1357,7 @@ static char * | |
165 | find_separate_debug_file (struct objfile *objfile) | |
166 | { | |
167 | asection *sect; | |
168 | - char *basename, *name_copy; | |
169 | + char *basename, *name_copy, *debugdir; | |
170 | char *dir = NULL; | |
171 | char *debugfile = NULL; | |
172 | char *canon_name = NULL; | |
173 | @@ -1410,29 +1434,51 @@ find_separate_debug_file (struct objfile *objfile) | |
174 | if (separate_debug_file_exists (debugfile, crc32, objfile->name)) | |
175 | goto cleanup_return_debugfile; | |
176 | ||
177 | - /* Then try in the global debugfile directory. */ | |
178 | - strcpy (debugfile, debug_file_directory); | |
179 | - strcat (debugfile, "/"); | |
180 | - strcat (debugfile, dir); | |
181 | - strcat (debugfile, basename); | |
182 | - | |
183 | - if (separate_debug_file_exists (debugfile, crc32, objfile->name)) | |
184 | - goto cleanup_return_debugfile; | |
185 | + /* Then try in the global debugfile directories. | |
186 | + | |
187 | + Keep backward compatibility so that DEBUG_FILE_DIRECTORY being "" will | |
188 | + cause "/..." lookups. */ | |
189 | ||
190 | - /* If the file is in the sysroot, try using its base path in the | |
191 | - global debugfile directory. */ | |
192 | - if (canon_name | |
193 | - && strncmp (canon_name, gdb_sysroot, strlen (gdb_sysroot)) == 0 | |
194 | - && IS_DIR_SEPARATOR (canon_name[strlen (gdb_sysroot)])) | |
195 | + debugdir = debug_file_directory; | |
196 | + do | |
197 | { | |
198 | - strcpy (debugfile, debug_file_directory); | |
199 | - strcat (debugfile, canon_name + strlen (gdb_sysroot)); | |
200 | + char *debugdir_end; | |
201 | + | |
202 | + while (*debugdir == DIRNAME_SEPARATOR) | |
203 | + debugdir++; | |
204 | + | |
205 | + debugdir_end = strchr (debugdir, DIRNAME_SEPARATOR); | |
206 | + if (debugdir_end == NULL) | |
207 | + debugdir_end = &debugdir[strlen (debugdir)]; | |
208 | + | |
209 | + memcpy (debugfile, debugdir, debugdir_end - debugdir); | |
210 | + debugfile[debugdir_end - debugdir] = 0; | |
211 | strcat (debugfile, "/"); | |
212 | + strcat (debugfile, dir); | |
213 | strcat (debugfile, basename); | |
214 | ||
215 | if (separate_debug_file_exists (debugfile, crc32, objfile->name)) | |
216 | goto cleanup_return_debugfile; | |
217 | + | |
218 | + /* If the file is in the sysroot, try using its base path in the | |
219 | + global debugfile directory. */ | |
220 | + if (canon_name | |
221 | + && strncmp (canon_name, gdb_sysroot, strlen (gdb_sysroot)) == 0 | |
222 | + && IS_DIR_SEPARATOR (canon_name[strlen (gdb_sysroot)])) | |
223 | + { | |
224 | + memcpy (debugfile, debugdir, debugdir_end - debugdir); | |
225 | + debugfile[debugdir_end - debugdir] = 0; | |
226 | + strcat (debugfile, canon_name + strlen (gdb_sysroot)); | |
227 | + strcat (debugfile, "/"); | |
228 | + strcat (debugfile, basename); | |
229 | + | |
230 | + if (separate_debug_file_exists (debugfile, crc32, objfile->name)) | |
231 | + goto cleanup_return_debugfile; | |
232 | + } | |
233 | + | |
234 | + debugdir = debugdir_end; | |
235 | } | |
236 | + while (*debugdir != 0); | |
237 | ||
238 | xfree (debugfile); | |
239 | debugfile = NULL; | |
240 | @@ -4173,12 +4219,12 @@ Usage: set extension-language .foo bar"), | |
241 | ||
242 | add_setshow_optional_filename_cmd ("debug-file-directory", class_support, | |
243 | &debug_file_directory, _("\ | |
244 | -Set the directory where separate debug symbols are searched for."), _("\ | |
245 | -Show the directory where separate debug symbols are searched for."), _("\ | |
246 | +Set the directories where separate debug symbols are searched for."), _("\ | |
247 | +Show the directories where separate debug symbols are searched for."), _("\ | |
248 | Separate debug symbols are first searched for in the same\n\ | |
249 | directory as the binary, then in the `" DEBUG_SUBDIRECTORY "' subdirectory,\n\ | |
250 | and lastly at the path of the directory of the binary with\n\ | |
251 | -the global debug-file directory prepended."), | |
252 | +each global debug-file-directory component prepended."), | |
253 | NULL, | |
254 | show_debug_file_directory, | |
255 | &setlist, &showlist); | |
256 | --- a/gdb/testsuite/gdb.base/sepdebug.exp | |
257 | +++ b/gdb/testsuite/gdb.base/sepdebug.exp | |
258 | @@ -995,6 +995,12 @@ if ![string compare $build_id_debug_filename ""] then { | |
259 | ||
260 | test_different_dir build-id "${objdir}/${subdir}" $xfail | |
261 | ||
262 | + # Test also multiple directories can be specified. Without the build-id | |
263 | + # reference GDB would find the separate debug info just at the same | |
264 | + # location as the executable file. | |
265 | + | |
266 | + test_different_dir multiple-dirs "/doesnotexist:${objdir}/${subdir}" $xfail | |
267 | + | |
268 | # Spare debug files may confuse testsuite runs in the future. | |
269 | remote_exec build "rm -f ${objdir}/${subdir}/${build_id_debug_filename}" | |
270 | } | |
271 |