12
12
#ifndef DRGN_DWARF_INDEX_H
13
13
#define DRGN_DWARF_INDEX_H
14
14
15
- #include <elfutils/libdw .h>
15
+ #include <elfutils/libdwfl .h>
16
16
#include <libelf.h>
17
17
#include <omp.h>
18
18
#include <stddef.h>
19
19
#include <stdint.h>
20
20
21
21
#include "drgn.h"
22
22
#include "hash_table.h"
23
+ #include "string_builder.h"
23
24
#include "vector.h"
24
25
25
26
/**
44
45
* @{
45
46
*/
46
47
47
- enum {
48
- SECTION_SYMTAB ,
49
- SECTION_DEBUG_ABBREV ,
50
- SECTION_DEBUG_INFO ,
51
- SECTION_DEBUG_LINE ,
52
- SECTION_DEBUG_STR ,
53
- DRGN_DWARF_INDEX_NUM_SECTIONS ,
54
- };
55
-
56
- struct drgn_dwarf_index_file {
57
- Elf_Data * sections [DRGN_DWARF_INDEX_NUM_SECTIONS ];
58
- bool failed ;
48
+ /**
49
+ * drgn-specific data for the @c Dwfl_Module userdata pointer.
50
+ *
51
+ * For a newly created userdata, @c indexed is @c false and @c err is @c NULL.
52
+ * They are updated by @ref drgn_dwarf_index_update(). @c err may be set with
53
+ * @ref drgn_dwfl_module_userdata_set_error() before @ref
54
+ * drgn_dwarf_index_update() is called to skip indexing for that module; the
55
+ * error message will be added to the @ref DRGN_ERROR_MISSING_DEBUG_INFO error.
56
+ *
57
+ * @sa drgn_dwfl_find_elf(), drgn_dwfl_section_address()
58
+ */
59
+ struct drgn_dwfl_module_userdata {
60
+ /** Whether the module is indexed in a @ref drgn_dwarf_index. */
61
+ bool indexed ;
62
+ /** File descriptor of @ref drgn_dwfl_module_userdata::elf. */
59
63
int fd ;
60
- /*
61
- * If this is NULL, then we didn't open the file and don't own the Elf
62
- * handle.
63
- */
64
- const char * path ;
64
+ /** Error encountered while indexing. */
65
+ struct drgn_error * err ;
66
+ /** Path of @ref drgn_dwfl_module_userdata::elf. */
67
+ char * path ;
68
+ /** ELF handle to use. */
65
69
Elf * elf ;
66
- Dwarf * dwarf ;
67
- Elf_Data * rela_sections [DRGN_DWARF_INDEX_NUM_SECTIONS ];
68
- struct drgn_dwarf_index_file * next ;
69
70
};
70
71
71
- static inline const char *
72
- drgn_dwarf_index_file_to_key (struct drgn_dwarf_index_file * const * entry )
72
+ struct drgn_dwfl_module_userdata * drgn_dwfl_module_userdata_create (void );
73
+
74
+ void
75
+ drgn_dwfl_module_userdata_destroy (struct drgn_dwfl_module_userdata * userdata );
76
+
77
+ /* This takes ownership of err. */
78
+ void
79
+ drgn_dwfl_module_userdata_set_error (struct drgn_dwfl_module_userdata * userdata ,
80
+ const char * message ,
81
+ struct drgn_error * err );
82
+
83
+ extern const Dwfl_Callbacks drgn_dwfl_callbacks ;
84
+
85
+ /** Get the @ref drgn_dwfl_module_userdata for a @c Dwfl_Module. */
86
+ static inline struct drgn_dwfl_module_userdata *
87
+ drgn_dwfl_module_userdata (Dwfl_Module * module )
73
88
{
74
- return (* entry )-> path ;
89
+ void * * userdatap ;
90
+
91
+ dwfl_module_info (module , & userdatap , NULL , NULL , NULL , NULL , NULL ,
92
+ NULL );
93
+ return * userdatap ;
75
94
}
76
- DEFINE_HASH_TABLE_TYPE (drgn_dwarf_index_file_table ,
77
- struct drgn_dwarf_index_file * ,
78
- drgn_dwarf_index_file_to_key )
79
95
80
96
struct drgn_dwarf_index_die ;
81
97
DEFINE_HASH_MAP_TYPE (drgn_dwarf_index_die_map , struct string , size_t )
@@ -102,23 +118,14 @@ struct drgn_dwarf_index_shard {
102
118
* files. It is much faster for this task than other generic DWARF parsing
103
119
* libraries.
104
120
*
105
- * A new DWARF index is created by @ref drgn_dwarf_index_create(). It is freed
106
- * by @ref drgn_dwarf_index_destroy().
107
- *
108
- * Indexing happens in two steps: the files to index are opened using @ref
109
- * drgn_dwarf_index_open(), then they all are parsed and indexed by @ref
110
- * drgn_dwarf_index_update(). The update step is parallelized across CPUs, so it
111
- * is most efficient to open as many files as possible before indexing them all
112
- * at once in parallel.
113
- *
114
121
* Searches in the index are done with a @ref drgn_dwarf_index_iterator.
115
122
*/
116
123
struct drgn_dwarf_index {
117
- /** @privatesection */
118
- struct drgn_dwarf_index_file_table files ;
119
- struct drgn_dwarf_index_file * opened_first , * opened_last ;
120
- struct drgn_dwarf_index_file * indexed_first , * indexed_last ;
121
- /* The index is sharded to reduce lock contention. */
124
+ /**
125
+ * Index shards.
126
+ *
127
+ * This is sharded to reduce lock contention.
128
+ */
122
129
struct drgn_dwarf_index_shard shards [1 << DRGN_DWARF_INDEX_SHARD_BITS ];
123
130
};
124
131
@@ -134,44 +141,36 @@ void drgn_dwarf_index_init(struct drgn_dwarf_index *dindex);
134
141
void drgn_dwarf_index_deinit (struct drgn_dwarf_index * dindex );
135
142
136
143
/**
137
- * Open a file and add it to a DWARF index .
144
+ * Index new DWARF information .
138
145
*
139
- * This function does the first part of indexing a file: it opens the file,
140
- * reads or maps it, and checks that it contains the required debugging
141
- * information. However, it does not actually parse the debugging information.
142
- * To do so, call drgn_dwarf_index_update() once all of the files to index have
143
- * been opened.
146
+ * This parses and indexes the debugging information for all modules in @p dwfl
147
+ * that have not yet been indexed.
144
148
*
145
- * If this fails, the file is not opened, but previously opened files are not
146
- * affected.
149
+ * On success, @ref drgn_dwfl_module_userdata::indexed is set to @c true for all
150
+ * modules that we were able to index, and @ref drgn_dwfl_module_userdata::err
151
+ * is set to non-@c NULL for all other modules.
152
+ *
153
+ * If debug information was not available for one or more modules, a @ref
154
+ * DRGN_ERROR_MISSING_DEBUG_INFO error is returned.
155
+ *
156
+ * On any other error, no new debugging information is indexed.
147
157
*
148
- * @param[in] dindex DWARF index.
149
- * @param[in] path Path to open.
150
- * @param[out] elf If not @c NULL, the opened ELF file. It is valid until @ref
151
- * drgn_dwarf_index_destroy() is called.
152
158
* @return @c NULL on success, non-@c NULL on error.
153
159
*/
154
- struct drgn_error * drgn_dwarf_index_open (struct drgn_dwarf_index * dindex ,
155
- const char * path , Elf * * elf );
156
-
157
- /** Close any files which haven't been indexed yet. */
158
- void drgn_dwarf_index_close_unindexed (struct drgn_dwarf_index * dindex );
160
+ struct drgn_error * drgn_dwarf_index_update (struct drgn_dwarf_index * dindex ,
161
+ Dwfl * dwfl );
159
162
160
163
/**
161
- * Index newly opened files.
162
- *
163
- * This function does the second part of indexing a file: it applies ELF
164
- * relocations, then parses and indexes the debugging information in all of the
165
- * files opened by @ref drgn_dwarf_index_open() since the last call to @ref
166
- * drgn_dwarf_index_update() or @ref drgn_dwarf_index_create().
167
- *
168
- * If this fails, no new debugging information is indexed and all opened files
169
- * which were not already indexed are closed.
164
+ * Remove all @c Dwfl_Modules that aren't indexed (see @ref
165
+ * drgn_dwfl_module_userdata::indexed) from @p dwfl.
170
166
*
171
- * @param[in] dindex DWARF index.
172
- * @return @c NULL on success, non-@c NULL on error .
167
+ * This should be called if @ref drgn_dwarf_index_update() returned an error or
168
+ * if modules were reported and @ref drgn_dwarf_index_update() was not called .
173
169
*/
174
- struct drgn_error * drgn_dwarf_index_update (struct drgn_dwarf_index * dindex );
170
+ void drgn_remove_unindexed_dwfl_modules (Dwfl * dwfl );
171
+
172
+ /** Remove all @Dwfl_Modules from @p dwfl. */
173
+ void drgn_remove_all_dwfl_modules (Dwfl * dwfl );
175
174
176
175
/**
177
176
* Iterator over DWARF debugging information.
@@ -215,14 +214,17 @@ void drgn_dwarf_index_iterator_init(struct drgn_dwarf_index_iterator *it,
215
214
*
216
215
* @param[in] it DWARF index iterator.
217
216
* @param[out] die_ret Returned DIE.
217
+ * @param[out] bias_ret Returned difference between addresses in the loaded
218
+ * module and addresses in the debugging information. This may be @c NULL if it
219
+ * is not needed.
218
220
* @return @c NULL on success, non-@c NULL on error. In particular, when there
219
221
* are no more matching DIEs, @p die_ret is not modified and an error with code
220
222
* @ref DRGN_ERROR_STOP is returned; this @ref DRGN_ERROR_STOP error does not
221
223
* have to be passed to @ref drgn_error_destroy().
222
224
*/
223
225
struct drgn_error *
224
226
drgn_dwarf_index_iterator_next (struct drgn_dwarf_index_iterator * it ,
225
- Dwarf_Die * die_ret );
227
+ Dwarf_Die * die_ret , uint64_t * bias_ret );
226
228
227
229
/** @} */
228
230
0 commit comments