drgn/libdrgn/orc_info.h
Omar Sandoval 18b12a5c7b libdrgn: get .eh_frame from the correct file
We're currently getting .eh_frame from the debug file. However, since
.eh_frame is an SHF_ALLOC section, it is actually in the loaded file,
and may not be in the debug file. This causes us to fail to unwind in
modules whose debug file was created with objcopy --only-keep-debug
(which is typical for Linux distro debug files).

Fix it by getting .eh_frame from the loaded file. To make this easier,
we split .eh_frame and .debug_frame data into two separate tables. We
also don't bother deduplicating them anymore, since GCC and Clang only
seem to generate one or the other in practice.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-28 13:37:29 -08:00

75 lines
1.6 KiB
C

// Copyright (c) Meta Platforms, Inc. and affiliates.
// SPDX-License-Identifier: LGPL-2.1-or-later
/**
* @file
*
* ORC unwinder support.
*
* See @ref DebugInfo.
*/
#ifndef DRGN_ORC_INFO_H
#define DRGN_ORC_INFO_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "cfi.h"
struct drgn_module;
/**
* @ingroup DebugInfo
*
* @{
*/
/** ORC unwinder data for a @ref drgn_module. */
struct drgn_module_orc_info {
/**
* Base for calculating program counter corresponding to an ORC unwinder
* entry.
*
* This is the address of the `.orc_unwind_ip` ELF section.
*
* @sa drgn_module_orc_info::entries
*/
uint64_t pc_base;
/**
* Offsets for calculating program counter corresponding to an ORC
* unwinder entry.
*
* This is the contents of the `.orc_unwind_ip` ELF section, byte
* swapped to the host's byte order if necessary.
*
* @sa drgn_module_orc_info::entries
*/
int32_t *pc_offsets;
/**
* ORC unwinder entries.
*
* This is the contents of the `.orc_unwind` ELF section, byte swapped
* to the host's byte order if necessary.
*
* Entry `i` specifies how to unwind the stack if
* `orc_pc(i) <= PC < orc_pc(i + 1)`, where
* `orc_pc(i) = pc_base + 4 * i + pc_offsets[i]`.
*/
struct drgn_orc_entry *entries;
/** Number of ORC unwinder entries. */
size_t num_entries;
};
void drgn_module_orc_info_deinit(struct drgn_module *module);
struct drgn_error *
drgn_module_find_orc_cfi(struct drgn_module *module, uint64_t pc,
struct drgn_cfi_row **row_ret, bool *interrupted_ret,
drgn_register_number *ret_addr_regno_ret);
/** @} */
#endif /* DRGN_ORC_INFO_H */