static void init_unwind_hdr()

in kernel/unwind.c [253:357]


static void init_unwind_hdr(struct unwind_table *table,
			    void *(*alloc) (unsigned long))
{
	const u8 *ptr;
	unsigned long tableSize = table->size, hdrSize;
	unsigned int n;
	const u32 *fde;
	struct {
		u8 version;
		u8 eh_frame_ptr_enc;
		u8 fde_count_enc;
		u8 table_enc;
		unsigned long eh_frame_ptr;
		unsigned int fde_count;
		struct eh_frame_hdr_table_entry table[];
	} __attribute__ ((__packed__)) *header;

	if (table->header)
		return;

	if (table->hdrsz)
		pr_warn(".eh_frame_hdr for '%s' present but unusable\n",
			table->name);

	if (tableSize & (sizeof(*fde) - 1))
		return;

	for (fde = table->address, n = 0;
	     tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
	     tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
		const u32 *cie = cie_for_fde(fde, table);
		signed ptrType;

		if (cie == &not_fde)
			continue;
		if (cie == NULL || cie == &bad_cie)
			goto ret_err;
		ptrType = fde_pointer_type(cie);
		if (ptrType < 0)
			goto ret_err;

		ptr = (const u8 *)(fde + 2);
		if (!read_pointer(&ptr, (const u8 *)(fde + 1) + *fde,
								ptrType)) {
			/* FIXME_Rajesh We have 4 instances of null addresses
			 * instead of the initial loc addr
			 * return;
			 */
			WARN(1, "unwinder: FDE->initial_location NULL %p\n",
				(const u8 *)(fde + 1) + *fde);
		}
		++n;
	}

	if (tableSize || !n)
		goto ret_err;

	hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int)
	    + 2 * n * sizeof(unsigned long);

	header = alloc(hdrSize);
	if (!header)
		goto ret_err;

	header->version = 1;
	header->eh_frame_ptr_enc = DW_EH_PE_abs | DW_EH_PE_native;
	header->fde_count_enc = DW_EH_PE_abs | DW_EH_PE_data4;
	header->table_enc = DW_EH_PE_abs | DW_EH_PE_native;
	put_unaligned((unsigned long)table->address, &header->eh_frame_ptr);
	BUILD_BUG_ON(offsetof(typeof(*header), fde_count)
		     % __alignof(typeof(header->fde_count)));
	header->fde_count = n;

	BUILD_BUG_ON(offsetof(typeof(*header), table)
		     % __alignof(typeof(*header->table)));
	for (fde = table->address, tableSize = table->size, n = 0;
	     tableSize;
	     tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
		const u32 *cie = __cie_for_fde(fde);

		if (fde[1] == CIE_ID)
			continue;	/* this is a CIE */
		ptr = (const u8 *)(fde + 2);
		header->table[n].start = read_pointer(&ptr,
						      (const u8 *)(fde + 1) +
						      *fde,
						      fde_pointer_type(cie));
		header->table[n].fde = (unsigned long)fde;
		++n;
	}
	WARN_ON(n != header->fde_count);

	sort(header->table,
	     n,
	     sizeof(*header->table),
	     cmp_eh_frame_hdr_table_entries, swap_eh_frame_hdr_table_entries);

	table->hdrsz = hdrSize;
	smp_wmb();
	table->header = (const void *)header;
	return;

ret_err:
	panic("Attention !!! Dwarf FDE parsing errors\n");
}