Branch data Line data Source code
1 : : /* Internal definitions for libdwfl.
2 : : Copyright (C) 2005-2015, 2018, 2024-2025 Red Hat, Inc.
3 : : This file is part of elfutils.
4 : :
5 : : This file is free software; you can redistribute it and/or modify
6 : : it under the terms of either
7 : :
8 : : * the GNU Lesser General Public License as published by the Free
9 : : Software Foundation; either version 3 of the License, or (at
10 : : your option) any later version
11 : :
12 : : or
13 : :
14 : : * the GNU General Public License as published by the Free
15 : : Software Foundation; either version 2 of the License, or (at
16 : : your option) any later version
17 : :
18 : : or both in parallel, as here.
19 : :
20 : : elfutils is distributed in the hope that it will be useful, but
21 : : WITHOUT ANY WARRANTY; without even the implied warranty of
22 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 : : General Public License for more details.
24 : :
25 : : You should have received copies of the GNU General Public License and
26 : : the GNU Lesser General Public License along with this program. If
27 : : not, see <http://www.gnu.org/licenses/>. */
28 : :
29 : : #ifndef _LIBDWFLP_H
30 : : #define _LIBDWFLP_H 1
31 : :
32 : : #include <libdwfl.h>
33 : : #include <libebl.h>
34 : : #include <assert.h>
35 : : #include <dirent.h>
36 : : #include <errno.h>
37 : : #include <stdbool.h>
38 : : #include <stdlib.h>
39 : : #include <string.h>
40 : :
41 : : #include "libdwP.h" /* We need its INTDECLs. */
42 : : #include "libdwelfP.h"
43 : : #include "eu-search.h"
44 : :
45 : : typedef struct Dwfl_Process Dwfl_Process;
46 : :
47 : : #define DWFL_ERRORS \
48 : : DWFL_ERROR (NOERROR, N_("no error")) \
49 : : DWFL_ERROR (UNKNOWN_ERROR, N_("unknown error")) \
50 : : DWFL_ERROR (NOMEM, N_("out of memory")) \
51 : : DWFL_ERROR (ERRNO, N_("See errno")) \
52 : : DWFL_ERROR (LIBELF, N_("See elf_errno")) \
53 : : DWFL_ERROR (LIBDW, N_("See dwarf_errno")) \
54 : : DWFL_ERROR (LIBEBL, N_("See ebl_errno (XXX missing)")) \
55 : : DWFL_ERROR (ZLIB, N_("gzip decompression failed")) \
56 : : DWFL_ERROR (BZLIB, N_("bzip2 decompression failed")) \
57 : : DWFL_ERROR (LZMA, N_("LZMA decompression failed")) \
58 : : DWFL_ERROR (ZSTD, N_("zstd decompression failed")) \
59 : : DWFL_ERROR (UNKNOWN_MACHINE, N_("no support library found for machine")) \
60 : : DWFL_ERROR (NOREL, N_("Callbacks missing for ET_REL file")) \
61 : : DWFL_ERROR (BADRELTYPE, N_("Unsupported relocation type")) \
62 : : DWFL_ERROR (BADRELOFF, N_("r_offset is bogus")) \
63 : : DWFL_ERROR (BADSTROFF, N_("offset out of range")) \
64 : : DWFL_ERROR (RELUNDEF, N_("relocation refers to undefined symbol")) \
65 : : DWFL_ERROR (CB, N_("Callback returned failure")) \
66 : : DWFL_ERROR (NO_DWARF, N_("No DWARF information found")) \
67 : : DWFL_ERROR (NO_SYMTAB, N_("No symbol table found")) \
68 : : DWFL_ERROR (NO_PHDR, N_("No ELF program headers")) \
69 : : DWFL_ERROR (OVERLAP, N_("address range overlaps an existing module")) \
70 : : DWFL_ERROR (ADDR_OUTOFRANGE, N_("address out of range")) \
71 : : DWFL_ERROR (NO_MATCH, N_("no matching address range")) \
72 : : DWFL_ERROR (TRUNCATED, N_("image truncated")) \
73 : : DWFL_ERROR (ALREADY_ELF, N_("ELF file opened")) \
74 : : DWFL_ERROR (BADELF, N_("not a valid ELF file")) \
75 : : DWFL_ERROR (WEIRD_TYPE, N_("cannot handle DWARF type description")) \
76 : : DWFL_ERROR (WRONG_ID_ELF, N_("ELF file does not match build ID")) \
77 : : DWFL_ERROR (BAD_PRELINK, N_("corrupt .gnu.prelink_undo section data")) \
78 : : DWFL_ERROR (LIBEBL_BAD, N_("Internal error due to ebl")) \
79 : : DWFL_ERROR (CORE_MISSING, N_("Missing data in core file")) \
80 : : DWFL_ERROR (INVALID_REGISTER, N_("Invalid register")) \
81 : : DWFL_ERROR (REGISTER_VAL_UNKNOWN, N_("Unknown register value")) \
82 : : DWFL_ERROR (PROCESS_MEMORY_READ, N_("Error reading process memory")) \
83 : : DWFL_ERROR (PROCESS_NO_ARCH, N_("Couldn't find architecture of any ELF")) \
84 : : DWFL_ERROR (PARSE_PROC, N_("Error parsing /proc filesystem")) \
85 : : DWFL_ERROR (INVALID_DWARF, N_("Invalid DWARF")) \
86 : : DWFL_ERROR (UNSUPPORTED_DWARF, N_("Unsupported DWARF")) \
87 : : DWFL_ERROR (NEXT_THREAD_FAIL, N_("Unable to find more threads")) \
88 : : DWFL_ERROR (ATTACH_STATE_CONFLICT, N_("Dwfl already has attached state")) \
89 : : DWFL_ERROR (NO_ATTACH_STATE, N_("Dwfl has no attached state")) \
90 : : DWFL_ERROR (NO_UNWIND, N_("Unwinding not supported for this architecture")) \
91 : : DWFL_ERROR (INVALID_ARGUMENT, N_("Invalid argument")) \
92 : : DWFL_ERROR (NO_CORE_FILE, N_("Not an ET_CORE ELF file"))
93 : :
94 : : #define DWFL_ERROR(name, text) DWFL_E_##name,
95 : : typedef enum { DWFL_ERRORS DWFL_E_NUM } Dwfl_Error;
96 : : #undef DWFL_ERROR
97 : :
98 : : #define OTHER_ERROR(name) ((unsigned int) DWFL_E_##name << 16)
99 : : #define DWFL_E(name, errno) (OTHER_ERROR (name) | (errno))
100 : :
101 : : extern int __libdwfl_canon_error (Dwfl_Error) internal_function;
102 : : extern void __libdwfl_seterrno (Dwfl_Error) internal_function;
103 : :
104 : : /* Resources we might keep for the user about the core file that the
105 : : Dwfl might have been created from. Can currently only be set
106 : : through std-argp. */
107 : : struct Dwfl_User_Core
108 : : {
109 : : char *executable_for_core; /* --executable if --core was specified. */
110 : : Elf *core; /* non-NULL if we need to free it. */
111 : : int fd; /* close if >= 0. */
112 : : };
113 : :
114 : : /* forward decl from ../libdwfl_stacktrace/ */
115 : : typedef struct Dwflst_Process_Tracker Dwflst_Process_Tracker;
116 : :
117 : : struct Dwfl
118 : : {
119 : : const Dwfl_Callbacks *callbacks;
120 : : Dwflst_Process_Tracker *tracker;
121 : : #ifdef ENABLE_LIBDEBUGINFOD
122 : : debuginfod_client *debuginfod;
123 : : #endif
124 : : Dwfl_Module *modulelist; /* List in order used by full traversals. */
125 : :
126 : : Dwfl_Process *process;
127 : : Dwfl_Error attacherr; /* Previous error attaching process. */
128 : :
129 : : GElf_Addr offline_next_address;
130 : :
131 : : GElf_Addr segment_align; /* Smallest granularity of segments. */
132 : :
133 : : /* Binary search table in three parallel malloc'd arrays. */
134 : : size_t lookup_elts; /* Elements in use. */
135 : : size_t lookup_alloc; /* Elements allococated. */
136 : : GElf_Addr *lookup_addr; /* Start address of segment. */
137 : : Dwfl_Module **lookup_module; /* Module associated with segment, or null. */
138 : : int *lookup_segndx; /* User segment index, or -1. */
139 : : int next_segndx;
140 : :
141 : : struct Dwfl_User_Core *user_core;
142 : : char *sysroot; /* sysroot, or NULL to search standard system
143 : : paths */
144 : :
145 : : /* Serialize debuginfod_client usage. */
146 : : mutex_define (, debuginfod_lock);
147 : : };
148 : :
149 : : #define OFFLINE_REDZONE 0x10000
150 : :
151 : : struct dwfl_file
152 : : {
153 : : char *name;
154 : : int fd;
155 : : bool valid; /* The build ID note has been matched. */
156 : : bool relocated; /* Partial relocation of all sections done. */
157 : :
158 : : Elf *elf;
159 : :
160 : : /* This is the lowest p_vaddr in this ELF file, aligned to p_align.
161 : : For a file without phdrs, this is zero. */
162 : : GElf_Addr vaddr;
163 : :
164 : : /* This is an address chosen for synchronization between the main file
165 : : and the debug file. See dwfl_module_getdwarf.c for how it's chosen. */
166 : : GElf_Addr address_sync;
167 : : };
168 : :
169 : : struct Dwfl_Module
170 : : {
171 : : Dwfl *dwfl;
172 : : struct Dwfl_Module *next; /* Link on Dwfl.modulelist. */
173 : :
174 : : void *userdata;
175 : :
176 : : char *name; /* Iterator name for this module. */
177 : : GElf_Addr low_addr, high_addr;
178 : :
179 : : struct dwfl_file main, debug, aux_sym;
180 : : GElf_Addr main_bias;
181 : : Ebl *ebl;
182 : : GElf_Half e_type; /* GElf_Ehdr.e_type cache. */
183 : : Dwfl_Error elferr; /* Previous failure to open main file. */
184 : :
185 : : struct dwfl_relocation *reloc_info; /* Relocatable sections. */
186 : :
187 : : struct dwfl_file *symfile; /* Either main or debug. */
188 : : Elf_Data *symdata; /* Data in the ELF symbol table section. */
189 : : Elf_Data *aux_symdata; /* Data in the auxiliary ELF symbol table. */
190 : : size_t syments; /* sh_size / sh_entsize of that section. */
191 : : size_t aux_syments; /* sh_size / sh_entsize of aux_sym section. */
192 : : int first_global; /* Index of first global symbol of table. */
193 : : int aux_first_global; /* Index of first global of aux_sym table. */
194 : : Elf_Data *symstrdata; /* Data for its string table. */
195 : : Elf_Data *aux_symstrdata; /* Data for aux_sym string table. */
196 : : Elf_Data *symxndxdata; /* Data in the extended section index table. */
197 : : Elf_Data *aux_symxndxdata; /* Data in the extended auxiliary table. */
198 : :
199 : : char *elfpath; /* The path where we found the main Elf. */
200 : :
201 : : Dwarf *dw; /* libdw handle for its debugging info. */
202 : : Dwarf *alt; /* Dwarf used for dwarf_setalt, or NULL. */
203 : : int alt_fd; /* descriptor, only valid when alt != NULL. */
204 : : Elf *alt_elf; /* Elf for alt Dwarf. */
205 : :
206 : : Dwfl_Error symerr; /* Previous failure to load symbols. */
207 : : Dwfl_Error dwerr; /* Previous failure to load DWARF. */
208 : :
209 : : /* Known CU's in this module. */
210 : : struct dwfl_cu *first_cu, **cu;
211 : :
212 : : search_tree lazy_cu_tree; /* Table indexed by Dwarf_Off of CU. */
213 : :
214 : : struct dwfl_arange *aranges; /* Mapping of addresses in module to CUs. */
215 : :
216 : : void *build_id_bits; /* malloc'd copy of build ID bits. */
217 : : GElf_Addr build_id_vaddr; /* Address where they reside, 0 if unknown. */
218 : : int build_id_len; /* -1 for prior failure, 0 if unset. */
219 : :
220 : : unsigned int ncu;
221 : : unsigned int lazycu; /* Possible users, deleted when none left. */
222 : : unsigned int naranges;
223 : :
224 : : Dwarf_CFI *dwarf_cfi; /* Cached DWARF CFI for this module. */
225 : : Dwarf_CFI *eh_cfi; /* Cached EH CFI for this module. */
226 : :
227 : : int segment; /* Index of first segment table entry. */
228 : : bool gc; /* Mark/sweep flag. */
229 : : bool is_executable; /* Use Dwfl::executable_for_core? */
230 : : };
231 : :
232 : : /* This holds information common for all the threads/tasks/TIDs of one process
233 : : for backtraces. */
234 : :
235 : : struct Dwfl_Process
236 : : {
237 : : struct Dwfl *dwfl;
238 : : pid_t pid;
239 : : const Dwfl_Thread_Callbacks *callbacks;
240 : : void *callbacks_arg;
241 : : struct ebl *ebl;
242 : : bool ebl_close:1;
243 : : };
244 : :
245 : : /* See its typedef in libdwfl.h. */
246 : :
247 : : struct Dwfl_Thread
248 : : {
249 : : Dwfl_Process *process;
250 : : pid_t tid;
251 : : /* Bottom (innermost) frame while we're initializing, NULL afterwards. */
252 : : Dwfl_Frame *unwound;
253 : : void *callbacks_arg;
254 : :
255 : : /* Data for handling AARCH64 (currently limited to demangling PAC from
256 : : return addresses). */
257 : : struct {
258 : : Dwarf_Addr pauth_insn_mask;
259 : : } aarch64;
260 : : };
261 : :
262 : : /* See its typedef in libdwfl.h. */
263 : :
264 : : struct Dwfl_Frame
265 : : {
266 : : Dwfl_Thread *thread;
267 : : /* Previous (outer) frame. */
268 : : Dwfl_Frame *unwound;
269 : : bool signal_frame : 1;
270 : : bool initial_frame : 1;
271 : : enum
272 : : {
273 : : /* This structure is still being initialized or there was an error
274 : : initializing it. */
275 : : DWFL_FRAME_STATE_ERROR,
276 : : /* PC field is valid. */
277 : : DWFL_FRAME_STATE_PC_SET,
278 : : /* PC field is undefined, this means the next (inner) frame was the
279 : : outermost frame. */
280 : : DWFL_FRAME_STATE_PC_UNDEFINED
281 : : } pc_state;
282 : : Dwfl_Unwound_Source unwound_source;
283 : : /* Either initialized from appropriate REGS element or on some archs
284 : : initialized separately as the return address has no DWARF register. */
285 : : Dwarf_Addr pc;
286 : : /* (1 << X) bitmask where 0 <= X < ebl_frame_nregs. */
287 : : uint64_t regs_set[3];
288 : : /* REGS array size is ebl_frame_nregs.
289 : : REGS_SET tells which of the REGS are valid. */
290 : : Dwarf_Addr regs[];
291 : : };
292 : :
293 : : /* Fetch value from Dwfl_Frame->regs indexed by DWARF REGNO. The
294 : : function returns 0 on success, -1 on error (invalid DWARF register
295 : : number), 1 if the value of the register in the frame is unknown.
296 : : Even on error, no error code is set. */
297 : : int __libdwfl_frame_reg_get (Dwfl_Frame *state, unsigned regno,
298 : : Dwarf_Addr *val)
299 : : internal_function;
300 : :
301 : : /* Store value to Dwfl_Frame->regs indexed by DWARF REGNO.
302 : : No error code is set if the function returns FALSE. */
303 : : bool __libdwfl_frame_reg_set (Dwfl_Frame *state, unsigned regno,
304 : : Dwarf_Addr val)
305 : : internal_function;
306 : :
307 : : /* Information cached about each CU in Dwfl_Module.dw. */
308 : : struct dwfl_cu
309 : : {
310 : : /* This caches libdw information about the CU. It's also the
311 : : address passed back to users, so we take advantage of the
312 : : fact that it's placed first to cast back. */
313 : : Dwarf_Die die;
314 : :
315 : : Dwfl_Module *mod; /* Pointer back to containing module. */
316 : :
317 : : struct dwfl_cu *next; /* CU immediately following in the file. */
318 : :
319 : : struct Dwfl_Lines *lines;
320 : : };
321 : :
322 : : struct Dwfl_Lines
323 : : {
324 : : struct dwfl_cu *cu;
325 : :
326 : : /* This is what the opaque Dwfl_Line * pointers we pass to users are.
327 : : We need to recover pointers to our struct dwfl_cu and a record in
328 : : libdw's Dwarf_Line table. To minimize the memory used in addition
329 : : to libdw's Dwarf_Lines buffer, we just point to our own index in
330 : : this table, and have one pointer back to the CU. The indices here
331 : : match those in libdw's Dwarf_CU.lines->info table. */
332 : : struct Dwfl_Line
333 : : {
334 : : unsigned int idx; /* My index in the dwfl_cu.lines table. */
335 : : } idx[0];
336 : : };
337 : :
338 : : static inline struct dwfl_cu *
339 : 2665804 : dwfl_linecu_inline (const Dwfl_Line *line)
340 : : {
341 [ + + - - : 2664542 : const struct Dwfl_Lines *lines = ((const void *) line
- - + + +
+ + - ]
342 : 2665804 : - offsetof (struct Dwfl_Lines,
343 : : idx[line->idx]));
344 [ + + ]: 2664542 : return lines->cu;
345 : : }
346 : : #define dwfl_linecu dwfl_linecu_inline
347 : :
348 : : static inline GElf_Addr
349 : 41290530 : dwfl_adjusted_address (Dwfl_Module *mod, GElf_Addr addr)
350 : : {
351 [ # # ]: 41290530 : return addr + mod->main_bias;
352 : : }
353 : :
354 : : static inline GElf_Addr
355 : 238726 : dwfl_deadjust_address (Dwfl_Module *mod, GElf_Addr addr)
356 : : {
357 : 238726 : return addr - mod->main_bias;
358 : : }
359 : :
360 : : static inline Dwarf_Addr
361 : 1809764 : dwfl_adjusted_dwarf_addr (Dwfl_Module *mod, Dwarf_Addr addr)
362 : : {
363 : 1809764 : return dwfl_adjusted_address (mod, (addr
364 : 1809764 : - mod->debug.address_sync
365 : 1809764 : + mod->main.address_sync));
366 : : }
367 : :
368 : : static inline Dwarf_Addr
369 : 904 : dwfl_deadjust_dwarf_addr (Dwfl_Module *mod, Dwarf_Addr addr)
370 : : {
371 : 904 : return (dwfl_deadjust_address (mod, addr)
372 : 904 : - mod->main.address_sync
373 : 904 : + mod->debug.address_sync);
374 : : }
375 : :
376 : : static inline Dwarf_Addr
377 : 78670 : dwfl_adjusted_aux_sym_addr (Dwfl_Module *mod, Dwarf_Addr addr)
378 : : {
379 : 78670 : return dwfl_adjusted_address (mod, (addr
380 : 78670 : - mod->aux_sym.address_sync
381 : 78670 : + mod->main.address_sync));
382 : : }
383 : :
384 : : static inline Dwarf_Addr
385 : 0 : dwfl_deadjust_aux_sym_addr (Dwfl_Module *mod, Dwarf_Addr addr)
386 : : {
387 : 0 : return (dwfl_deadjust_address (mod, addr)
388 : 0 : - mod->main.address_sync
389 : 0 : + mod->aux_sym.address_sync);
390 : : }
391 : :
392 : : static inline GElf_Addr
393 : 39830086 : dwfl_adjusted_st_value (Dwfl_Module *mod, Elf *symelf, GElf_Addr addr)
394 : : {
395 [ + + ]: 39830086 : if (symelf == mod->main.elf)
396 : 39315370 : return dwfl_adjusted_address (mod, addr);
397 [ + + ]: 514716 : if (symelf == mod->debug.elf)
398 : 436046 : return dwfl_adjusted_dwarf_addr (mod, addr);
399 : 78670 : return dwfl_adjusted_aux_sym_addr (mod, addr);
400 : : }
401 : :
402 : : static inline GElf_Addr
403 : 237822 : dwfl_deadjust_st_value (Dwfl_Module *mod, Elf *symelf, GElf_Addr addr)
404 : : {
405 [ + - ]: 237822 : if (symelf == mod->main.elf)
406 : 237822 : return dwfl_deadjust_address (mod, addr);
407 [ # # ]: 0 : if (symelf == mod->debug.elf)
408 : 0 : return dwfl_deadjust_dwarf_addr (mod, addr);
409 : 0 : return dwfl_deadjust_aux_sym_addr (mod, addr);
410 : : }
411 : :
412 : : /* This describes a contiguous address range that lies in a single CU.
413 : : We condense runs of Dwarf_Arange entries for the same CU into this. */
414 : : struct dwfl_arange
415 : : {
416 : : struct dwfl_cu *cu;
417 : : size_t arange; /* Index in Dwarf_Aranges. */
418 : : };
419 : :
420 : : #define __LIBDWFL_REMOTE_MEM_CACHE_SIZE 4096
421 : : /* Structure for caching remote memory reads as used by __libdwfl_pid_arg. */
422 : : struct __libdwfl_remote_mem_cache
423 : : {
424 : : Dwarf_Addr addr; /* Remote address. */
425 : : Dwarf_Off len; /* Zero if cleared, otherwise likely 4K. */
426 : : unsigned char buf[__LIBDWFL_REMOTE_MEM_CACHE_SIZE]; /* The actual cache. */
427 : : };
428 : :
429 : : /* Structure used for keeping track of ptrace attaching a thread.
430 : : Shared by linux-pid-attach and linux-proc-maps. If it has been setup
431 : : then get the instance through __libdwfl_get_pid_arg. */
432 : : struct __libdwfl_pid_arg
433 : : {
434 : : /* /proc/PID/task/. */
435 : : DIR *dir;
436 : : /* Elf for /proc/PID/exe. Set to NULL if it couldn't be opened. */
437 : : Elf *elf;
438 : : /* Remote memory cache, NULL if there is no memory cached.
439 : : Should be cleared on detachment (because that makes the thread
440 : : runnable and the cache invalid). */
441 : : struct __libdwfl_remote_mem_cache *mem_cache;
442 : : /* fd for /proc/PID/exe. Set to -1 if it couldn't be opened. */
443 : : int elf_fd;
444 : : /* It is 0 if not used. */
445 : : pid_t tid_attached;
446 : : /* Valid only if TID_ATTACHED is not zero. */
447 : : bool tid_was_stopped;
448 : : /* True if threads are ptrace stopped by caller. */
449 : : bool assume_ptrace_stopped;
450 : : };
451 : :
452 : : /* If DWfl is not NULL and a Dwfl_Process has been setup that has
453 : : Dwfl_Thread_Callbacks set to pid_thread_callbacks, then return the
454 : : callbacks_arg, which will be a struct __libdwfl_pid_arg. Otherwise
455 : : returns NULL. */
456 : : extern struct __libdwfl_pid_arg *__libdwfl_get_pid_arg (Dwfl *dwfl)
457 : : internal_function;
458 : :
459 : : /* Makes sure the given tid is attached. On success returns true and
460 : : sets tid_was_stopped. */
461 : : extern bool __libdwfl_ptrace_attach (pid_t tid, bool *tid_was_stoppedp)
462 : : internal_function;
463 : :
464 : : /* Detaches a tid that was attached through
465 : : __libdwfl_ptrace_attach. Must be given the tid_was_stopped as set
466 : : by __libdwfl_ptrace_attach. */
467 : : extern void __libdwfl_ptrace_detach (pid_t tid, bool tid_was_stopped)
468 : : internal_function;
469 : :
470 : :
471 : : /* Internal wrapper for old dwfl_module_getsym and new dwfl_module_getsym_info.
472 : : adjust_st_value set to true returns adjusted SYM st_value, set to false
473 : : it will not adjust SYM at all, but does match against resolved *ADDR. */
474 : : extern const char *__libdwfl_getsym (Dwfl_Module *mod, int ndx, GElf_Sym *sym,
475 : : GElf_Addr *addr, GElf_Word *shndxp,
476 : : Elf **elfp, Dwarf_Addr *biasp,
477 : : bool *resolved, bool adjust_st_value)
478 : : internal_function;
479 : :
480 : : extern void __libdwfl_module_free (Dwfl_Module *mod) internal_function;
481 : :
482 : : /* Find the main ELF file, update MOD->elferr and/or MOD->main.elf. */
483 : : extern void __libdwfl_getelf (Dwfl_Module *mod) internal_function;
484 : :
485 : : /* Process relocations in debugging sections in an ET_REL file.
486 : : FILE must be opened with ELF_C_READ_MMAP_PRIVATE or ELF_C_READ,
487 : : to make it possible to relocate the data in place (or ELF_C_RDWR or
488 : : ELF_C_RDWR_MMAP if you intend to modify the Elf file on disk). After
489 : : this, dwarf_begin_elf on FILE will read the relocated data.
490 : :
491 : : When DEBUG is false, apply partial relocation to all sections. */
492 : : extern Dwfl_Error __libdwfl_relocate (Dwfl_Module *mod, Elf *file, bool debug)
493 : : internal_function;
494 : :
495 : : /* Find the section index in mod->main.elf that contains the given
496 : : *ADDR. Adjusts *ADDR to be section relative on success, returns
497 : : SHN_UNDEF on failure. */
498 : : extern size_t __libdwfl_find_section_ndx (Dwfl_Module *mod, Dwarf_Addr *addr)
499 : : internal_function;
500 : :
501 : : /* Process (simple) relocations in arbitrary section TSCN of an ET_REL file.
502 : : RELOCSCN is SHT_REL or SHT_RELA and TSCN is its sh_info target section. */
503 : : extern Dwfl_Error __libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated,
504 : : Elf_Scn *relocscn, Elf_Scn *tscn,
505 : : bool partial)
506 : : internal_function;
507 : :
508 : : /* Adjust *VALUE from section-relative to absolute.
509 : : MOD->dwfl->callbacks->section_address is called to determine the actual
510 : : address of a loaded section. */
511 : : extern Dwfl_Error __libdwfl_relocate_value (Dwfl_Module *mod, Elf *elf,
512 : : size_t *shstrndx_cache,
513 : : Elf32_Word shndx,
514 : : GElf_Addr *value)
515 : : internal_function;
516 : :
517 : : /* Ensure that MOD->ebl is set up. */
518 : : extern Dwfl_Error __libdwfl_module_getebl (Dwfl_Module *mod) internal_function;
519 : :
520 : : /* Install a new Dwarf_CFI in *SLOT (MOD->eh_cfi or MOD->dwarf_cfi). */
521 : : extern Dwarf_CFI *__libdwfl_set_cfi (Dwfl_Module *mod, Dwarf_CFI **slot,
522 : : Dwarf_CFI *cfi)
523 : : internal_function;
524 : :
525 : : /* Iterate through all the CU's in the module. Start by passing a null
526 : : LASTCU, and then pass the last *CU returned. Success return with null
527 : : *CU no more CUs. */
528 : : extern Dwfl_Error __libdwfl_nextcu (Dwfl_Module *mod, struct dwfl_cu *lastcu,
529 : : struct dwfl_cu **cu) internal_function;
530 : :
531 : : /* Find the CU by address. */
532 : : extern Dwfl_Error __libdwfl_addrcu (Dwfl_Module *mod, Dwarf_Addr addr,
533 : : struct dwfl_cu **cu) internal_function;
534 : :
535 : : /* Ensure that CU->lines (and CU->cu->lines) is set up. */
536 : : extern Dwfl_Error __libdwfl_cu_getsrclines (struct dwfl_cu *cu)
537 : : internal_function;
538 : :
539 : : /* Look in ELF for an NT_GNU_BUILD_ID note. Store it to BUILD_ID_BITS,
540 : : its vaddr in ELF to BUILD_ID_VADDR (it is unrelocated, even if MOD is not
541 : : NULL) and store length to BUILD_ID_LEN. Returns -1 for errors, 1 if it was
542 : : stored and 0 if no note is found. MOD may be NULL, MOD must be non-NULL
543 : : only if ELF is ET_REL. */
544 : : extern int __libdwfl_find_elf_build_id (Dwfl_Module *mod, Elf *elf,
545 : : const void **build_id_bits,
546 : : GElf_Addr *build_id_elfaddr,
547 : : int *build_id_len)
548 : : internal_function;
549 : :
550 : : /* Look in ELF for an NT_GNU_BUILD_ID note. If SET is true, store it
551 : : in MOD and return its length. If SET is false, instead compare it
552 : : to that stored in MOD and return 2 if they match, 1 if they do not.
553 : : Returns -1 for errors, 0 if no note is found. */
554 : : extern int __libdwfl_find_build_id (Dwfl_Module *mod, bool set, Elf *elf)
555 : : internal_function;
556 : :
557 : : /* Open a main or debuginfo file by its build ID, returns the fd. */
558 : : extern int __libdwfl_open_mod_by_build_id (Dwfl_Module *mod, bool debug,
559 : : char **file_name) internal_function;
560 : :
561 : : /* Same, but takes an explicit build_id, can also be used for alt debug. */
562 : : extern int __libdwfl_open_by_build_id (Dwfl_Module *mod, bool debug,
563 : : char **file_name, const size_t id_len,
564 : : const uint8_t *id) internal_function;
565 : :
566 : : extern uint32_t __libdwfl_crc32 (uint32_t crc, unsigned char *buf, size_t len)
567 : : attribute_hidden;
568 : : extern int __libdwfl_crc32_file (int fd, uint32_t *resp) attribute_hidden;
569 : :
570 : :
571 : : /* Given ELF and some parameters return TRUE if the *P return value parameters
572 : : have been successfully filled in. Any of the *P parameters can be NULL. */
573 : : extern bool __libdwfl_elf_address_range (Elf *elf, GElf_Addr base,
574 : : bool add_p_vaddr, bool sanity,
575 : : GElf_Addr *vaddrp,
576 : : GElf_Addr *address_syncp,
577 : : GElf_Addr *startp, GElf_Addr *endp,
578 : : GElf_Addr *biasp, GElf_Half *e_typep)
579 : : internal_function;
580 : :
581 : : /* Meat of dwfl_report_elf, given elf_begin just called.
582 : : Consumes ELF on success, not on failure. */
583 : : extern Dwfl_Module *__libdwfl_report_elf (Dwfl *dwfl, const char *name,
584 : : const char *file_name, int fd,
585 : : Elf *elf, GElf_Addr base,
586 : : bool add_p_vaddr, bool sanity)
587 : : internal_function;
588 : :
589 : : /* Meat of dwfl_report_offline. */
590 : : extern Dwfl_Module *__libdwfl_report_offline (Dwfl *dwfl, const char *name,
591 : : const char *file_name,
592 : : int fd, bool closefd,
593 : : int (*predicate) (const char *,
594 : : const char *))
595 : : internal_function;
596 : :
597 : : /* Free PROCESS. Unlink and free also any structures it references. */
598 : : extern void __libdwfl_process_free (Dwfl_Process *process)
599 : : internal_function;
600 : :
601 : : /* Basic implementation of Dwfl_Thread_Callbacks.set_initial_registers.
602 : : ARG must be a Dwfl_Thread *. Calls dwfl_thread_state_register_pc
603 : : if firstreg is -1 (indicating arch PC), dwfl_thread_state_registers
604 : : otherwise. */
605 : : extern bool __libdwfl_set_initial_registers_thread (int firstreg,
606 : : unsigned nregs,
607 : : const Dwarf_Word *regs,
608 : : void *arg);
609 : :
610 : : /* Update STATE->unwound for the unwound frame.
611 : : On error STATE->unwound == NULL
612 : : or STATE->unwound->pc_state == DWFL_FRAME_STATE_ERROR;
613 : : in such case dwfl_errno () is set.
614 : : If STATE->unwound->pc_state == DWFL_FRAME_STATE_PC_UNDEFINED
615 : : then STATE was the last valid frame. */
616 : : extern void __libdwfl_frame_unwind (Dwfl_Frame *state)
617 : : internal_function;
618 : :
619 : : /* Align segment START downwards or END upwards addresses according to DWFL. */
620 : : extern GElf_Addr __libdwfl_segment_start (Dwfl *dwfl, GElf_Addr start)
621 : : internal_function;
622 : : extern GElf_Addr __libdwfl_segment_end (Dwfl *dwfl, GElf_Addr end)
623 : : internal_function;
624 : :
625 : : /* Decompression wrappers: decompress whole file into memory. */
626 : : extern Dwfl_Error __libdw_gunzip (int fd, off_t start_offset,
627 : : void *mapped, size_t mapped_size,
628 : : void **whole, size_t *whole_size)
629 : : internal_function;
630 : : extern Dwfl_Error __libdw_bunzip2 (int fd, off_t start_offset,
631 : : void *mapped, size_t mapped_size,
632 : : void **whole, size_t *whole_size)
633 : : internal_function;
634 : : extern Dwfl_Error __libdw_unlzma (int fd, off_t start_offset,
635 : : void *mapped, size_t mapped_size,
636 : : void **whole, size_t *whole_size)
637 : : internal_function;
638 : : extern Dwfl_Error __libdw_unzstd (int fd, off_t start_offset,
639 : : void *mapped, size_t mapped_size,
640 : : void **whole, size_t *whole_size)
641 : : internal_function;
642 : :
643 : : /* Skip the image header before a file image: updates *START_OFFSET. */
644 : : extern Dwfl_Error __libdw_image_header (int fd, off_t *start_offset,
645 : : void *mapped, size_t mapped_size)
646 : : internal_function;
647 : :
648 : : /* Open Elf handle on *FDP. This handles decompression and checks
649 : : elf_kind. Succeed only for ELF_K_ELF, or also ELF_K_AR if ARCHIVE_OK.
650 : : Returns DWFL_E_NOERROR and sets *ELFP on success, resets *FDP to -1 if
651 : : it's no longer used. Resets *FDP on failure too iff CLOSE_ON_FAIL. */
652 : : extern Dwfl_Error __libdw_open_file (int *fdp, Elf **elfp,
653 : : bool close_on_fail, bool archive_ok)
654 : : internal_function;
655 : :
656 : : /* Same as __libdw_open_file, but opens Elf handle from memory region. */
657 : : extern Dwfl_Error __libdw_open_elf_memory (char *data, size_t size, Elf **elfp,
658 : : bool archive_ok)
659 : : internal_function;
660 : :
661 : : /* Same as __libdw_open_file, but never closes the given file
662 : : descriptor and ELF_K_AR is always an acceptable type. */
663 : : extern Dwfl_Error __libdw_open_elf (int fd, Elf **elfp) internal_function;
664 : :
665 : : /* Fetch PT_DYNAMIC P_VADDR from ELF and store it to *VADDRP. Return success.
666 : : *VADDRP is not modified if the function fails. */
667 : : extern bool __libdwfl_dynamic_vaddr_get (Elf *elf, GElf_Addr *vaddrp)
668 : : internal_function;
669 : :
670 : : #ifdef ENABLE_LIBDEBUGINFOD
671 : : /* Internal interface to libdebuginfod (if installed). */
672 : : int
673 : : __libdwfl_debuginfod_find_executable (Dwfl *dwfl,
674 : : const unsigned char *build_id_bits,
675 : : size_t build_id_len);
676 : : int
677 : : __libdwfl_debuginfod_find_debuginfo (Dwfl *dwfl,
678 : : const unsigned char *build_id_bits,
679 : : size_t build_id_len);
680 : : void
681 : : __libdwfl_debuginfod_end (debuginfod_client *c);
682 : : #endif
683 : :
684 : :
685 : : /* These are working nicely for --core, but are not ready to be
686 : : exported interfaces quite yet. */
687 : :
688 : : /* Type of callback function ...
689 : : */
690 : : typedef bool Dwfl_Memory_Callback (Dwfl *dwfl, int segndx,
691 : : void **buffer, size_t *buffer_available,
692 : : GElf_Addr vaddr, size_t minread, void *arg);
693 : :
694 : : /* Type of callback function ...
695 : : */
696 : : typedef bool Dwfl_Module_Callback (Dwfl_Module *mod, void **userdata,
697 : : const char *name, Dwarf_Addr base,
698 : : void **buffer, size_t *buffer_available,
699 : : GElf_Off cost, GElf_Off worthwhile,
700 : : GElf_Off whole, GElf_Off contiguous,
701 : : void *arg, Elf **elfp);
702 : :
703 : : /* One shared library (or executable) info from DT_DEBUG link map. */
704 : : struct r_debug_info_module
705 : : {
706 : : struct r_debug_info_module *next;
707 : : /* FD is -1 iff ELF is NULL. */
708 : : int fd;
709 : : Elf *elf;
710 : : GElf_Addr l_ld;
711 : : /* START and END are both zero if not valid. */
712 : : GElf_Addr start, end;
713 : : bool disk_file_has_build_id;
714 : : char name[0];
715 : : };
716 : :
717 : : /* Information gathered from DT_DEBUG by dwfl_link_map_report hinted to
718 : : dwfl_segment_report_module. */
719 : : struct r_debug_info
720 : : {
721 : : struct r_debug_info_module *module;
722 : : };
723 : :
724 : : /* ...
725 : : */
726 : : extern int dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
727 : : const char *executable,
728 : : Dwfl_Memory_Callback *memory_callback,
729 : : void *memory_callback_arg,
730 : : Dwfl_Module_Callback *read_eagerly,
731 : : void *read_eagerly_arg,
732 : : size_t maxread,
733 : : const void *note_file,
734 : : size_t note_file_size,
735 : : const struct r_debug_info *r_debug_info);
736 : :
737 : : /* Report a module for entry in the dynamic linker's struct link_map list.
738 : : For each link_map entry, if an existing module resides at its address,
739 : : this just modifies that module's name and suggested file name. If
740 : : no such module exists, this calls dwfl_report_elf on the l_name string.
741 : :
742 : : If AUXV is not null, it points to AUXV_SIZE bytes of auxiliary vector
743 : : data as contained in an NT_AUXV note or read from a /proc/pid/auxv
744 : : file. When this is available, it guides the search. If AUXV is null
745 : : or the memory it points to is not accessible, then this search can
746 : : only find where to begin if the correct executable file was
747 : : previously reported and preloaded as with dwfl_report_elf.
748 : :
749 : : Fill in R_DEBUG_INFO if it is not NULL. It should be cleared by the
750 : : caller, this function does not touch fields it does not need to modify.
751 : : If R_DEBUG_INFO is not NULL then no modules get added to DWFL, caller
752 : : has to add them from filled in R_DEBUG_INFO.
753 : :
754 : : Returns the number of modules found, or -1 for errors. */
755 : : extern int dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
756 : : Dwfl_Memory_Callback *memory_callback,
757 : : void *memory_callback_arg,
758 : : struct r_debug_info *r_debug_info);
759 : :
760 : :
761 : : /* Avoid PLT entries. */
762 : : INTDECL (dwfl_begin)
763 : : INTDECL (dwfl_end)
764 : : INTDECL (dwfl_errmsg)
765 : : INTDECL (dwfl_errno)
766 : : INTDECL (dwfl_addrmodule)
767 : : INTDECL (dwfl_addrsegment)
768 : : INTDECL (dwfl_addrdwarf)
769 : : INTDECL (dwfl_addrdie)
770 : : INTDECL (dwfl_core_file_attach)
771 : : INTDECL (dwfl_core_file_report)
772 : : INTDECL (dwfl_getmodules)
773 : : INTDECL (dwfl_module_addrdie)
774 : : INTDECL (dwfl_module_address_section)
775 : : INTDECL (dwfl_module_addrinfo)
776 : : INTDECL (dwfl_module_addrsym)
777 : : INTDECL (dwfl_module_build_id)
778 : : INTDECL (dwfl_module_getdwarf)
779 : : INTDECL (dwfl_module_getelf)
780 : : INTDECL (dwfl_module_getsym)
781 : : INTDECL (dwfl_module_getsym_info)
782 : : INTDECL (dwfl_module_getsymtab)
783 : : INTDECL (dwfl_module_getsymtab_first_global)
784 : : INTDECL (dwfl_module_getsrc)
785 : : INTDECL (dwfl_module_report_build_id)
786 : : INTDECL (dwfl_report_elf)
787 : : INTDECL (dwfl_report_begin)
788 : : INTDECL (dwfl_report_begin_add)
789 : : INTDECL (dwfl_report_module)
790 : : INTDECL (dwfl_report_segment)
791 : : INTDECL (dwfl_report_offline)
792 : : INTDECL (dwfl_report_offline_memory)
793 : : INTDECL (dwfl_report_end)
794 : : INTDECL (dwfl_build_id_find_elf)
795 : : INTDECL (dwfl_build_id_find_debuginfo)
796 : : INTDECL (dwfl_standard_find_debuginfo)
797 : : INTDECL (dwfl_link_map_report)
798 : : INTDECL (dwfl_linux_kernel_find_elf)
799 : : INTDECL (dwfl_linux_kernel_module_section_address)
800 : : INTDECL (dwfl_linux_proc_attach)
801 : : INTDECL (dwfl_linux_proc_report)
802 : : INTDECL (dwfl_linux_proc_maps_report)
803 : : INTDECL (dwfl_linux_proc_find_elf)
804 : : INTDECL (dwfl_linux_kernel_report_kernel)
805 : : INTDECL (dwfl_linux_kernel_report_modules)
806 : : INTDECL (dwfl_linux_kernel_report_offline)
807 : : INTDECL (dwfl_offline_section_address)
808 : : INTDECL (dwfl_module_relocate_address)
809 : : INTDECL (dwfl_module_dwarf_cfi)
810 : : INTDECL (dwfl_module_eh_cfi)
811 : : INTDECL (dwfl_attach_state)
812 : : INTDECL (dwfl_pid)
813 : : INTDECL (dwfl_thread_dwfl)
814 : : INTDECL (dwfl_thread_tid)
815 : : INTDECL (dwfl_frame_thread)
816 : : INTDECL (dwfl_frame_unwound_source)
817 : : INTDECL (dwfl_unwound_source_str)
818 : : INTDECL (dwfl_thread_state_registers)
819 : : INTDECL (dwfl_thread_state_register_pc)
820 : : INTDECL (dwfl_getthread_frames)
821 : : INTDECL (dwfl_getthreads)
822 : : INTDECL (dwfl_thread_getframes)
823 : : INTDECL (dwfl_frame_pc)
824 : : INTDECL (dwfl_frame_reg)
825 : : INTDECL (dwfl_get_debuginfod_client)
826 : :
827 : : /* Leading arguments standard to callbacks passed a Dwfl_Module. */
828 : : #define MODCB_ARGS(mod) (mod), &(mod)->userdata, (mod)->name, (mod)->low_addr
829 : : #define CBFAIL (errno ? DWFL_E (ERRNO, errno) : DWFL_E_CB);
830 : :
831 : :
832 : : /* The default used by dwfl_standard_find_debuginfo. */
833 : : #define DEFAULT_DEBUGINFO_PATH ":.debug:/usr/lib/debug"
834 : :
835 : :
836 : : #endif /* libdwflP.h */
|