arch/arc/kernel/unwind.c

Source file repositories/reference/linux-study-clean/arch/arc/kernel/unwind.c

File Facts

System
Linux kernel
Corpus path
arch/arc/kernel/unwind.c
Extension
.c
Size
32936 bytes
Lines
1307
Domain
Architecture Layer
Bucket
arch/arc
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.

Dependency Surface

Detected Declarations

Annotated Snippet

struct unwind_item {
	enum item_location {
		Nowhere,
		Memory,
		Register,
		Value
	} where;
	uleb128_t value;
};

struct unwind_state {
	uleb128_t loc, org;
	const u8 *cieStart, *cieEnd;
	uleb128_t codeAlign;
	sleb128_t dataAlign;
	struct cfa {
		uleb128_t reg, offs;
	} cfa;
	struct unwind_item regs[ARRAY_SIZE(reg_info)];
	unsigned stackDepth:8;
	unsigned version:8;
	const u8 *label;
	const u8 *stack[MAX_STACK_DEPTH];
};

static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 };

static struct unwind_table *find_table(unsigned long pc)
{
	struct unwind_table *table;

	for (table = &root_table; table; table = table->link)
		if ((pc >= table->core.pc
		     && pc < table->core.pc + table->core.range)
		    || (pc >= table->init.pc
			&& pc < table->init.pc + table->init.range))
			break;

	return table;
}

static unsigned long read_pointer(const u8 **pLoc,
				  const void *end, signed ptrType);
static void init_unwind_hdr(struct unwind_table *table,
			    void *(*alloc) (unsigned long));

/*
 * wrappers for header alloc (vs. calling one vs. other at call site)
 * to elide section mismatches warnings
 */
static void *__init unw_hdr_alloc_early(unsigned long sz)
{
	return memblock_alloc_from(sz, sizeof(unsigned int), MAX_DMA_ADDRESS);
}

static void init_unwind_table(struct unwind_table *table, const char *name,
			      const void *core_start, unsigned long core_size,
			      const void *init_start, unsigned long init_size,
			      const void *table_start, unsigned long table_size,
			      const u8 *header_start, unsigned long header_size)
{
	table->core.pc = (unsigned long)core_start;
	table->core.range = core_size;
	table->init.pc = (unsigned long)init_start;
	table->init.range = init_size;
	table->address = table_start;
	table->size = table_size;
	/* To avoid the pointer addition with NULL pointer.*/
	if (header_start != NULL) {
		const u8 *ptr = header_start + 4;
		const u8 *end = header_start + header_size;
		/* See if the linker provided table looks valid. */
		if (header_size <= 4
		|| header_start[0] != 1
		|| (void *)read_pointer(&ptr, end, header_start[1])
				!= table_start
		|| header_start[2] == DW_EH_PE_omit
		|| read_pointer(&ptr, end, header_start[2]) <= 0
		|| header_start[3] == DW_EH_PE_omit)
			header_start = NULL;
	}
	table->hdrsz = header_size;
	smp_wmb();
	table->header = header_start;
	table->link = NULL;
	table->name = name;
}

void __init arc_unwind_init(void)
{

Annotation

Implementation Notes