2727 */
2828#define KSYM_NAME_LEN 128
2929
30- struct funcs_layout {
31- unsigned long mcount_start ;
32- unsigned long mcount_stop ;
33- unsigned long mcount_sec_idx ;
34- };
35-
3630struct elf_function {
3731 const char * name ;
38- unsigned long addr ;
39- unsigned long size ;
40- unsigned long sh_addr ;
4132 bool generated ;
4233};
4334
@@ -64,12 +55,9 @@ static void delete_functions(void)
6455#define max (x , y ) ((x) < (y) ? (y) : (x))
6556#endif
6657
67- static int collect_function (struct btf_elf * btfe , GElf_Sym * sym ,
68- size_t sym_sec_idx )
58+ static int collect_function (struct btf_elf * btfe , GElf_Sym * sym )
6959{
7060 struct elf_function * new ;
71- static GElf_Shdr sh ;
72- static size_t last_idx ;
7361 const char * name ;
7462
7563 if (elf_sym__type (sym ) != STT_FUNC )
@@ -91,257 +79,12 @@ static int collect_function(struct btf_elf *btfe, GElf_Sym *sym,
9179 functions = new ;
9280 }
9381
94- if (sym_sec_idx != last_idx ) {
95- if (!elf_section_by_idx (btfe -> elf , & sh , sym_sec_idx ))
96- return 0 ;
97- last_idx = sym_sec_idx ;
98- }
99-
10082 functions [functions_cnt ].name = name ;
101- functions [functions_cnt ].addr = elf_sym__value (sym );
102- functions [functions_cnt ].size = elf_sym__size (sym );
103- functions [functions_cnt ].sh_addr = sh .sh_addr ;
10483 functions [functions_cnt ].generated = false;
10584 functions_cnt ++ ;
10685 return 0 ;
10786}
10887
109- static int addrs_cmp (const void * _a , const void * _b )
110- {
111- const __u64 * a = _a ;
112- const __u64 * b = _b ;
113-
114- if (* a == * b )
115- return 0 ;
116- return * a < * b ? -1 : 1 ;
117- }
118-
119- static int get_vmlinux_addrs (struct btf_elf * btfe , struct funcs_layout * fl ,
120- __u64 * * paddrs , __u64 * pcount )
121- {
122- __u64 * addrs , count , offset ;
123- unsigned int addr_size , i ;
124- Elf_Data * data ;
125- GElf_Shdr shdr ;
126- Elf_Scn * sec ;
127-
128- /* Initialize for the sake of all error paths below. */
129- * paddrs = NULL ;
130- * pcount = 0 ;
131-
132- if (!fl -> mcount_start || !fl -> mcount_stop )
133- return 0 ;
134-
135- /*
136- * Find mcount addressed marked by __start_mcount_loc
137- * and __stop_mcount_loc symbols and load them into
138- * sorted array.
139- */
140- sec = elf_getscn (btfe -> elf , fl -> mcount_sec_idx );
141- if (!sec || !gelf_getshdr (sec , & shdr )) {
142- fprintf (stderr , "Failed to get section(%lu) header.\n" ,
143- fl -> mcount_sec_idx );
144- return -1 ;
145- }
146-
147- /* Get address size from processed file's ELF class. */
148- addr_size = gelf_getclass (btfe -> elf ) == ELFCLASS32 ? 4 : 8 ;
149-
150- offset = fl -> mcount_start - shdr .sh_addr ;
151- count = (fl -> mcount_stop - fl -> mcount_start ) / addr_size ;
152-
153- data = elf_getdata (sec , 0 );
154- if (!data ) {
155- fprintf (stderr , "Failed to get section(%lu) data.\n" ,
156- fl -> mcount_sec_idx );
157- return -1 ;
158- }
159-
160- addrs = malloc (count * sizeof (addrs [0 ]));
161- if (!addrs ) {
162- fprintf (stderr , "Failed to allocate memory for ftrace addresses.\n" );
163- return -1 ;
164- }
165-
166- if (addr_size == sizeof (__u64 )) {
167- memcpy (addrs , data -> d_buf + offset , count * addr_size );
168- } else {
169- for (i = 0 ; i < count ; i ++ )
170- addrs [i ] = (__u64 ) * ((__u32 * ) (data -> d_buf + offset + i * addr_size ));
171- }
172-
173- * paddrs = addrs ;
174- * pcount = count ;
175- return 0 ;
176- }
177-
178- static int
179- get_kmod_addrs (struct btf_elf * btfe , __u64 * * paddrs , __u64 * pcount )
180- {
181- __u64 * addrs , count ;
182- unsigned int addr_size , i ;
183- GElf_Shdr shdr_mcount ;
184- Elf_Data * data ;
185- Elf_Scn * sec ;
186-
187- /* Initialize for the sake of all error paths below. */
188- * paddrs = NULL ;
189- * pcount = 0 ;
190-
191- /* get __mcount_loc */
192- sec = elf_section_by_name (btfe -> elf , & btfe -> ehdr , & shdr_mcount ,
193- "__mcount_loc" , NULL );
194- if (!sec ) {
195- if (btf_elf__verbose ) {
196- printf ("%s: '%s' doesn't have __mcount_loc section\n" , __func__ ,
197- btfe -> filename );
198- }
199- return 0 ;
200- }
201-
202- data = elf_getdata (sec , NULL );
203- if (!data ) {
204- fprintf (stderr , "Failed to data for __mcount_loc section.\n" );
205- return -1 ;
206- }
207-
208- /* Get address size from processed file's ELF class. */
209- addr_size = gelf_getclass (btfe -> elf ) == ELFCLASS32 ? 4 : 8 ;
210-
211- count = data -> d_size / addr_size ;
212-
213- addrs = malloc (count * sizeof (addrs [0 ]));
214- if (!addrs ) {
215- fprintf (stderr , "Failed to allocate memory for ftrace addresses.\n" );
216- return -1 ;
217- }
218-
219- if (addr_size == sizeof (__u64 )) {
220- memcpy (addrs , data -> d_buf , count * addr_size );
221- } else {
222- for (i = 0 ; i < count ; i ++ )
223- addrs [i ] = (__u64 ) * ((__u32 * ) (data -> d_buf + i * addr_size ));
224- }
225-
226- /*
227- * We get Elf object from dwfl_module_getelf function,
228- * which performs all possible relocations, including
229- * __mcount_loc section.
230- *
231- * So addrs array now contains relocated values, which
232- * we need take into account when we compare them to
233- * functions values, see comment in setup_functions
234- * function.
235- */
236- * paddrs = addrs ;
237- * pcount = count ;
238- return 0 ;
239- }
240-
241- static int is_ftrace_func (struct elf_function * func , __u64 * addrs , __u64 count )
242- {
243- __u64 start = func -> addr ;
244- __u64 addr , end = func -> addr + func -> size ;
245-
246- /*
247- * The invariant here is addr[r] that is the smallest address
248- * that is >= than function start addr. Except the corner case
249- * where there is no such r, but for that we have a final check
250- * in the return.
251- */
252- size_t l = 0 , r = count - 1 , m ;
253-
254- /* make sure we don't use invalid r */
255- if (count == 0 )
256- return false;
257-
258- while (l < r ) {
259- m = l + (r - l ) / 2 ;
260- addr = addrs [m ];
261-
262- if (addr >= start ) {
263- /* we satisfy invariant, so tighten r */
264- r = m ;
265- } else {
266- /* m is not good enough as l, maybe m + 1 will be */
267- l = m + 1 ;
268- }
269- }
270-
271- return start <= addrs [r ] && addrs [r ] < end ;
272- }
273-
274- static int setup_functions (struct btf_elf * btfe , struct funcs_layout * fl )
275- {
276- __u64 * addrs , count , i ;
277- int functions_valid = 0 ;
278- bool kmod = false;
279-
280- /*
281- * Check if we are processing vmlinux image and
282- * get mcount data if it's detected.
283- */
284- if (get_vmlinux_addrs (btfe , fl , & addrs , & count ))
285- return -1 ;
286-
287- /*
288- * Check if we are processing kernel module and
289- * get mcount data if it's detected.
290- */
291- if (!addrs ) {
292- if (get_kmod_addrs (btfe , & addrs , & count ))
293- return -1 ;
294- kmod = true;
295- }
296-
297- if (!addrs ) {
298- if (btf_elf__verbose )
299- printf ("ftrace symbols not detected, falling back to DWARF data\n" );
300- delete_functions ();
301- return 0 ;
302- }
303-
304- qsort (addrs , count , sizeof (addrs [0 ]), addrs_cmp );
305- qsort (functions , functions_cnt , sizeof (functions [0 ]), functions_cmp );
306-
307- /*
308- * Let's got through all collected functions and filter
309- * out those that are not in ftrace.
310- */
311- for (i = 0 ; i < functions_cnt ; i ++ ) {
312- struct elf_function * func = & functions [i ];
313- /*
314- * For vmlinux image both addrs[x] and functions[x]::addr
315- * values are final address and are comparable.
316- *
317- * For kernel module addrs[x] is final address, but
318- * functions[x]::addr is relative address within section
319- * and needs to be relocated by adding sh_addr.
320- */
321- if (kmod )
322- func -> addr += func -> sh_addr ;
323-
324- /* Make sure function is within ftrace addresses. */
325- if (is_ftrace_func (func , addrs , count )) {
326- /*
327- * We iterate over sorted array, so we can easily skip
328- * not valid item and move following valid field into
329- * its place, and still keep the 'new' array sorted.
330- */
331- if (i != functions_valid )
332- functions [functions_valid ] = functions [i ];
333- functions_valid ++ ;
334- }
335- }
336-
337- functions_cnt = functions_valid ;
338- free (addrs );
339-
340- if (btf_elf__verbose )
341- printf ("Found %d functions!\n" , functions_cnt );
342- return 0 ;
343- }
344-
34588static struct elf_function * find_function (const struct btf_elf * btfe ,
34689 const char * name )
34790{
@@ -620,23 +363,8 @@ static int collect_percpu_var(struct btf_elf *btfe, GElf_Sym *sym,
620363 return 0 ;
621364}
622365
623- static void collect_symbol (GElf_Sym * sym , struct funcs_layout * fl ,
624- size_t sym_sec_idx )
625- {
626- if (!fl -> mcount_start &&
627- !strcmp ("__start_mcount_loc" , elf_sym__name (sym , btfe -> symtab ))) {
628- fl -> mcount_start = sym -> st_value ;
629- fl -> mcount_sec_idx = sym_sec_idx ;
630- }
631-
632- if (!fl -> mcount_stop &&
633- !strcmp ("__stop_mcount_loc" , elf_sym__name (sym , btfe -> symtab )))
634- fl -> mcount_stop = sym -> st_value ;
635- }
636-
637366static int collect_symbols (struct btf_elf * btfe , bool collect_percpu_vars )
638367{
639- struct funcs_layout fl = { };
640368 Elf32_Word sym_sec_idx ;
641369 uint32_t core_id ;
642370 GElf_Sym sym ;
@@ -648,9 +376,8 @@ static int collect_symbols(struct btf_elf *btfe, bool collect_percpu_vars)
648376 elf_symtab__for_each_symbol_index (btfe -> symtab , core_id , sym , sym_sec_idx ) {
649377 if (collect_percpu_vars && collect_percpu_var (btfe , & sym , sym_sec_idx ))
650378 return -1 ;
651- if (collect_function (btfe , & sym , sym_sec_idx ))
379+ if (collect_function (btfe , & sym ))
652380 return -1 ;
653- collect_symbol (& sym , & fl , sym_sec_idx );
654381 }
655382
656383 if (collect_percpu_vars ) {
@@ -661,9 +388,11 @@ static int collect_symbols(struct btf_elf *btfe, bool collect_percpu_vars)
661388 printf ("Found %d per-CPU variables!\n" , percpu_var_cnt );
662389 }
663390
664- if (functions_cnt && setup_functions (btfe , & fl )) {
665- fprintf (stderr , "Failed to filter DWARF functions\n" );
666- return -1 ;
391+ if (functions_cnt ) {
392+ qsort (functions , functions_cnt , sizeof (functions [0 ]),
393+ functions_cmp );
394+ if (btf_elf__verbose )
395+ printf ("Found %d functions!\n" , functions_cnt );
667396 }
668397
669398 return 0 ;
0 commit comments