arch/arm/kernel/unwind.c
Source file repositories/reference/linux-study-clean/arch/arm/kernel/unwind.c
File Facts
- System
- Linux kernel
- Corpus path
arch/arm/kernel/unwind.c- Extension
.c- Size
- 15651 bytes
- Lines
- 611
- Domain
- Architecture Layer
- Bucket
- arch/arm
- Inferred role
- Architecture Layer: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.
- CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/kernel.hlinux/init.hlinux/export.hlinux/sched.hlinux/slab.hlinux/spinlock.hlinux/list.hlinux/module.hasm/stacktrace.hasm/traps.hasm/unwind.hreboot.h
Detected Declarations
struct unwind_ctrl_blockenum regsfunction Copyrightfunction __aeabi_unwind_cpp_pr1function __aeabi_unwind_cpp_pr2function list_for_each_entryfunction unwind_get_bytefunction unwind_pop_registerfunction unwind_exec_pop_subset_r4_to_r13function unwind_exec_pop_r4_to_rNfunction unwind_exec_pop_subset_r0_to_r3function unwind_decode_uleb128function unwind_exec_insnfunction unwind_framefunction unwind_backtracefunction unwind_table_delexport __aeabi_unwind_cpp_pr0export __aeabi_unwind_cpp_pr1export __aeabi_unwind_cpp_pr2
Annotated Snippet
struct unwind_ctrl_block {
unsigned long vrs[16]; /* virtual register set */
const unsigned long *insn; /* pointer to the current instructions word */
unsigned long sp_high; /* highest value of sp allowed */
unsigned long *lr_addr; /* address of LR value on the stack */
/*
* 1 : check for stack overflow for each register pop.
* 0 : save overhead if there is plenty of stack remaining.
*/
int check_each_pop;
int entries; /* number of entries left to interpret */
int byte; /* current byte number in the instructions word */
};
enum regs {
#ifdef CONFIG_THUMB2_KERNEL
FP = 7,
#else
FP = 11,
#endif
SP = 13,
LR = 14,
PC = 15
};
extern const struct unwind_idx __start_unwind_idx[];
static const struct unwind_idx *__origin_unwind_idx;
extern const struct unwind_idx __stop_unwind_idx[];
static DEFINE_RAW_SPINLOCK(unwind_lock);
static LIST_HEAD(unwind_tables);
/* Convert a prel31 symbol to an absolute address */
#define prel31_to_addr(ptr) \
({ \
/* sign-extend to 32 bits */ \
long offset = (((long)*(ptr)) << 1) >> 1; \
(unsigned long)(ptr) + offset; \
})
/*
* Binary search in the unwind index. The entries are
* guaranteed to be sorted in ascending order by the linker.
*
* start = first entry
* origin = first entry with positive offset (or stop if there is no such entry)
* stop - 1 = last entry
*/
static const struct unwind_idx *search_index(unsigned long addr,
const struct unwind_idx *start,
const struct unwind_idx *origin,
const struct unwind_idx *stop)
{
unsigned long addr_prel31;
pr_debug("%s(%08lx, %p, %p, %p)\n",
__func__, addr, start, origin, stop);
/*
* only search in the section with the matching sign. This way the
* prel31 numbers can be compared as unsigned longs.
*/
if (addr < (unsigned long)start)
/* negative offsets: [start; origin) */
stop = origin;
else
/* positive offsets: [origin; stop) */
start = origin;
/* prel31 for address relavive to start */
addr_prel31 = (addr - (unsigned long)start) & 0x7fffffff;
while (start < stop - 1) {
const struct unwind_idx *mid = start + ((stop - start) >> 1);
/*
* As addr_prel31 is relative to start an offset is needed to
* make it relative to mid.
*/
if (addr_prel31 - ((unsigned long)mid - (unsigned long)start) <
mid->addr_offset)
stop = mid;
else {
/* keep addr_prel31 relative to start */
addr_prel31 -= ((unsigned long)mid -
(unsigned long)start);
start = mid;
}
}
Annotation
- Immediate include surface: `linux/kernel.h`, `linux/init.h`, `linux/export.h`, `linux/sched.h`, `linux/slab.h`, `linux/spinlock.h`, `linux/list.h`, `linux/module.h`.
- Detected declarations: `struct unwind_ctrl_block`, `enum regs`, `function Copyright`, `function __aeabi_unwind_cpp_pr1`, `function __aeabi_unwind_cpp_pr2`, `function list_for_each_entry`, `function unwind_get_byte`, `function unwind_pop_register`, `function unwind_exec_pop_subset_r4_to_r13`, `function unwind_exec_pop_r4_to_rN`.
- Atlas domain: Architecture Layer / arch/arm.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.