~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/util/unwind-libdw.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /tools/perf/util/unwind-libdw.c (Version linux-6.12-rc7) and /tools/perf/util/unwind-libdw.c (Version linux-5.15.169)


** Warning: Cannot open xref database.

  1 // SPDX-License-Identifier: GPL-2.0                 1 
  2 #include <linux/compiler.h>                       
  3 #include <elfutils/libdw.h>                       
  4 #include <elfutils/libdwfl.h>                     
  5 #include <inttypes.h>                             
  6 #include <errno.h>                                
  7 #include "debug.h"                                
  8 #include "dso.h"                                  
  9 #include "unwind.h"                               
 10 #include "unwind-libdw.h"                         
 11 #include "machine.h"                              
 12 #include "map.h"                                  
 13 #include "symbol.h"                               
 14 #include "thread.h"                               
 15 #include <linux/types.h>                          
 16 #include <linux/zalloc.h>                         
 17 #include "event.h"                                
 18 #include "perf_regs.h"                            
 19 #include "callchain.h"                            
 20 #include "util/env.h"                             
 21                                                   
 22 static char *debuginfo_path;                      
 23                                                   
 24 static int __find_debuginfo(Dwfl_Module *mod _    
 25                             const char *modnam    
 26                             const char *file_n    
 27                             GElf_Word debuglin    
 28 {                                                 
 29         const struct dso *dso = *userdata;        
 30                                                   
 31         assert(dso);                              
 32         if (dso__symsrc_filename(dso) && strcm    
 33                 *debuginfo_file_name = strdup(    
 34         return -1;                                
 35 }                                                 
 36                                                   
 37 static const Dwfl_Callbacks offline_callbacks     
 38         .find_debuginfo         = __find_debug    
 39         .debuginfo_path         = &debuginfo_p    
 40         .section_address        = dwfl_offline    
 41         // .find_elf is not set as we use dwfl    
 42 };                                                
 43                                                   
 44 static int __report_module(struct addr_locatio    
 45                             struct unwind_info    
 46 {                                                 
 47         Dwfl_Module *mod;                         
 48         struct dso *dso = NULL;                   
 49         Dwarf_Addr base;                          
 50         /*                                        
 51          * Some callers will use al->sym, so w    
 52          * cheaper thread__find_map() here.       
 53          */                                       
 54         thread__find_symbol(ui->thread, PERF_R    
 55                                                   
 56         if (al->map)                              
 57                 dso = map__dso(al->map);          
 58                                                   
 59         if (!dso)                                 
 60                 return 0;                         
 61                                                   
 62         /*                                        
 63          * The generated JIT DSO files only ma    
 64          * ELF headers.  Since JIT codes used     
 65          * segment, calculating the base addre    
 66          * a different code in another DSO.  S    
 67          * directly to pick the correct one.      
 68          */                                       
 69         if (!strncmp(dso__long_name(dso), "/tm    
 70                 base = map__start(al->map);       
 71         else                                      
 72                 base = map__start(al->map) - m    
 73                                                   
 74         mod = dwfl_addrmodule(ui->dwfl, ip);      
 75         if (mod) {                                
 76                 Dwarf_Addr s;                     
 77                                                   
 78                 dwfl_module_info(mod, NULL, &s    
 79                 if (s != base)                    
 80                         mod = NULL;               
 81         }                                         
 82                                                   
 83         if (!mod) {                               
 84                 char filename[PATH_MAX];          
 85                                                   
 86                 __symbol__join_symfs(filename,    
 87                 mod = dwfl_report_elf(ui->dwfl    
 88                                       base, fa    
 89         }                                         
 90         if (!mod) {                               
 91                 char filename[PATH_MAX];          
 92                                                   
 93                 if (dso__build_id_filename(dso    
 94                         mod = dwfl_report_elf(    
 95                                                   
 96         }                                         
 97                                                   
 98         if (mod) {                                
 99                 void **userdatap;                 
100                                                   
101                 dwfl_module_info(mod, &userdat    
102                 *userdatap = dso;                 
103         }                                         
104                                                   
105         return mod && dwfl_addrmodule(ui->dwfl    
106 }                                                 
107                                                   
108 static int report_module(u64 ip, struct unwind    
109 {                                                 
110         struct addr_location al;                  
111         int res;                                  
112                                                   
113         addr_location__init(&al);                 
114         res = __report_module(&al, ip, ui);       
115         addr_location__exit(&al);                 
116         return res;                               
117 }                                                 
118                                                   
119 /*                                                
120  * Store all entries within entries array,        
121  * we will process it after we finish unwind.     
122  */                                               
123 static int entry(u64 ip, struct unwind_info *u    
124                                                   
125 {                                                 
126         struct unwind_entry *e = &ui->entries[    
127         struct addr_location al;                  
128                                                   
129         addr_location__init(&al);                 
130         if (__report_module(&al, ip, ui)) {       
131                 addr_location__exit(&al);         
132                 return -1;                        
133         }                                         
134                                                   
135         e->ip     = ip;                           
136         e->ms.maps = al.maps;                     
137         e->ms.map = al.map;                       
138         e->ms.sym = al.sym;                       
139                                                   
140         pr_debug("unwind: %s:ip = 0x%" PRIx64     
141                  al.sym ? al.sym->name : "''",    
142                  ip,                              
143                  al.map ? map__map_ip(al.map,     
144         addr_location__exit(&al);                 
145         return 0;                                 
146 }                                                 
147                                                   
148 static pid_t next_thread(Dwfl *dwfl, void *arg    
149 {                                                 
150         /* We want only single thread to be pr    
151         if (*thread_argp != NULL)                 
152                 return 0;                         
153                                                   
154         *thread_argp = arg;                       
155         return dwfl_pid(dwfl);                    
156 }                                                 
157                                                   
158 static int access_dso_mem(struct unwind_info *    
159                           Dwarf_Word *data)       
160 {                                                 
161         struct addr_location al;                  
162         ssize_t size;                             
163         struct dso *dso;                          
164                                                   
165         addr_location__init(&al);                 
166         if (!thread__find_map(ui->thread, PERF    
167                 pr_debug("unwind: no map for %    
168                 goto out_fail;                    
169         }                                         
170         dso = map__dso(al.map);                   
171         if (!dso)                                 
172                 goto out_fail;                    
173                                                   
174         size = dso__data_read_addr(dso, al.map    
175                                                   
176         addr_location__exit(&al);                 
177         return !(size == sizeof(*data));          
178 out_fail:                                         
179         addr_location__exit(&al);                 
180         return -1;                                
181 }                                                 
182                                                   
183 static bool memory_read(Dwfl *dwfl __maybe_unu    
184                         void *arg)                
185 {                                                 
186         struct unwind_info *ui = arg;             
187         const char *arch = perf_env__arch(ui->    
188         struct stack_dump *stack = &ui->sample    
189         u64 start, end;                           
190         int offset;                               
191         int ret;                                  
192                                                   
193         ret = perf_reg_value(&start, &ui->samp    
194                              perf_arch_reg_sp(    
195         if (ret)                                  
196                 return false;                     
197                                                   
198         end = start + stack->size;                
199                                                   
200         /* Check overflow. */                     
201         if (addr + sizeof(Dwarf_Word) < addr)     
202                 return false;                     
203                                                   
204         if (addr < start || addr + sizeof(Dwar    
205                 ret = access_dso_mem(ui, addr,    
206                 if (ret) {                        
207                         pr_debug("unwind: acce    
208                                  " 0x%" PRIx64    
209                                 addr, start, e    
210                         return false;             
211                 }                                 
212                 return true;                      
213         }                                         
214                                                   
215         offset  = addr - start;                   
216         *result = *(Dwarf_Word *)&stack->data[    
217         pr_debug("unwind: access_mem addr 0x%"    
218                  addr, (unsigned long)*result,    
219         return true;                              
220 }                                                 
221                                                   
222 static const Dwfl_Thread_Callbacks callbacks =    
223         .next_thread            = next_thread,    
224         .memory_read            = memory_read,    
225         .set_initial_registers  = libdw__arch_    
226 };                                                
227                                                   
228 static int                                        
229 frame_callback(Dwfl_Frame *state, void *arg)      
230 {                                                 
231         struct unwind_info *ui = arg;             
232         Dwarf_Addr pc;                            
233         bool isactivation;                        
234                                                   
235         if (!dwfl_frame_pc(state, &pc, NULL))     
236                 if (!ui->best_effort)             
237                         pr_err("%s", dwfl_errm    
238                 return DWARF_CB_ABORT;            
239         }                                         
240                                                   
241         // report the module before we query f    
242         report_module(pc, ui);                    
243                                                   
244         if (!dwfl_frame_pc(state, &pc, &isacti    
245                 if (!ui->best_effort)             
246                         pr_err("%s", dwfl_errm    
247                 return DWARF_CB_ABORT;            
248         }                                         
249                                                   
250         if (!isactivation)                        
251                 --pc;                             
252                                                   
253         return entry(pc, ui) || !(--ui->max_st    
254                DWARF_CB_ABORT : DWARF_CB_OK;      
255 }                                                 
256                                                   
257 int unwind__get_entries(unwind_entry_cb_t cb,     
258                         struct thread *thread,    
259                         struct perf_sample *da    
260                         int max_stack,            
261                         bool best_effort)         
262 {                                                 
263         struct unwind_info *ui, ui_buf = {        
264                 .sample         = data,           
265                 .thread         = thread,         
266                 .machine        = maps__machin    
267                 .cb             = cb,             
268                 .arg            = arg,            
269                 .max_stack      = max_stack,      
270                 .best_effort    = best_effort     
271         };                                        
272         const char *arch = perf_env__arch(ui_b    
273         Dwarf_Word ip;                            
274         int err = -EINVAL, i;                     
275                                                   
276         if (!data->user_regs.regs)                
277                 return -EINVAL;                   
278                                                   
279         ui = zalloc(sizeof(ui_buf) + sizeof(ui    
280         if (!ui)                                  
281                 return -ENOMEM;                   
282                                                   
283         *ui = ui_buf;                             
284                                                   
285         ui->dwfl = dwfl_begin(&offline_callbac    
286         if (!ui->dwfl)                            
287                 goto out;                         
288                                                   
289         err = perf_reg_value(&ip, &data->user_    
290         if (err)                                  
291                 goto out;                         
292                                                   
293         err = report_module(ip, ui);              
294         if (err)                                  
295                 goto out;                         
296                                                   
297         err = !dwfl_attach_state(ui->dwfl, EM_    
298         if (err)                                  
299                 goto out;                         
300                                                   
301         err = dwfl_getthread_frames(ui->dwfl,     
302                                                   
303         if (err && ui->max_stack != max_stack)    
304                 err = 0;                          
305                                                   
306         /*                                        
307          * Display what we got based on the or    
308          */                                       
309         for (i = 0; i < ui->idx && !err; i++)     
310                 int j = i;                        
311                                                   
312                 if (callchain_param.order == O    
313                         j = ui->idx - i - 1;      
314                                                   
315                 err = ui->entries[j].ip ? ui->    
316         }                                         
317                                                   
318  out:                                             
319         if (err)                                  
320                 pr_debug("unwind: failed with     
321                                                   
322         dwfl_end(ui->dwfl);                       
323         free(ui);                                 
324         return 0;                                 
325 }                                                 
326                                                   

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php