scripts/mod/symsearch.c

Source file repositories/reference/linux-study-clean/scripts/mod/symsearch.c

File Facts

System
Linux kernel
Corpus path
scripts/mod/symsearch.c
Extension
.c
Size
5912 bytes
Lines
200
Domain
Support Tooling And Documentation
Bucket
scripts
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

struct syminfo {
	unsigned int symbol_index;
	unsigned int section_index;
	Elf_Addr addr;
};

/*
 * Container used to hold an entire binary search table.
 * Entries in table are ascending, sorted first by section_index,
 * then by addr, and last by symbol_index.  The sorting by
 * symbol_index is used to ensure predictable behavior when
 * multiple symbols are present with the same address; all
 * symbols past the first are effectively ignored, by eliding
 * them in symsearch_fixup().
 */
struct symsearch {
	unsigned int table_size;
	struct syminfo table[];
};

static int syminfo_compare(const void *s1, const void *s2)
{
	const struct syminfo *sym1 = s1;
	const struct syminfo *sym2 = s2;

	if (sym1->section_index > sym2->section_index)
		return 1;
	if (sym1->section_index < sym2->section_index)
		return -1;
	if (sym1->addr > sym2->addr)
		return 1;
	if (sym1->addr < sym2->addr)
		return -1;
	if (sym1->symbol_index > sym2->symbol_index)
		return 1;
	if (sym1->symbol_index < sym2->symbol_index)
		return -1;
	return 0;
}

static unsigned int symbol_count(struct elf_info *elf)
{
	unsigned int result = 0;

	for (Elf_Sym *sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
		if (is_valid_name(elf, sym))
			result++;
	}
	return result;
}

/*
 * Populate the search array that we just allocated.
 * Be slightly paranoid here.  The ELF file is mmap'd and could
 * conceivably change between symbol_count() and symsearch_populate().
 * If we notice any difference, bail out rather than potentially
 * propagating errors or crashing.
 */
static void symsearch_populate(struct elf_info *elf,
			       struct syminfo *table,
			       unsigned int table_size)
{
	bool is_arm = (elf->hdr->e_machine == EM_ARM);

	for (Elf_Sym *sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
		if (is_valid_name(elf, sym)) {
			if (table_size-- == 0)
				fatal("%s: size mismatch\n", __func__);
			table->symbol_index = sym - elf->symtab_start;
			table->section_index = get_secindex(elf, sym);
			table->addr = sym->st_value;

			/*
			 * For ARM Thumb instruction, the bit 0 of st_value is
			 * set if the symbol is STT_FUNC type. Mask it to get
			 * the address.
			 */
			if (is_arm && ELF_ST_TYPE(sym->st_info) == STT_FUNC)
				table->addr &= ~1;

			table++;
		}
	}

	if (table_size != 0)
		fatal("%s: size mismatch\n", __func__);
}

/*
 * Do any fixups on the table after sorting.

Annotation

Implementation Notes