scripts/gendwarfksyms/symbols.c

Source file repositories/reference/linux-study-clean/scripts/gendwarfksyms/symbols.c

File Facts

System
Linux kernel
Corpus path
scripts/gendwarfksyms/symbols.c
Extension
.c
Size
7859 bytes
Lines
345
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

symbol_addr_hash(&sym->addr)) {
		if (match == sym)
			continue; /* Already processed */

		if (match->addr.section == sym->addr.section &&
		    match->addr.address == sym->addr.address) {
			func(match, data);
			++processed;
		}
	}

	return processed;
}

/*
 * For symbols without debugging information (e.g. symbols defined in other
 * TUs), we also match __gendwarfksyms_ptr_<symbol_name> symbols, which the
 * kernel uses to ensure type information is present in the TU that exports
 * the symbol. A __gendwarfksyms_ptr pointer must have the same type as the
 * exported symbol, e.g.:
 *
 *   typeof(symname) *__gendwarf_ptr_symname = &symname;
 */
bool is_symbol_ptr(const char *name)
{
	return name && !strncmp(name, SYMBOL_PTR_PREFIX, SYMBOL_PTR_PREFIX_LEN);
}

static unsigned int for_each(const char *name, symbol_callback_t func,
			     void *data)
{
	struct hlist_node *tmp;
	struct symbol *match;

	if (!name || !*name)
		return 0;
	if (is_symbol_ptr(name))
		name += SYMBOL_PTR_PREFIX_LEN;

	hash_for_each_possible_safe(symbol_names, match, tmp, name_hash,
				    hash_str(name)) {
		if (strcmp(match->name, name))
			continue;

		/* Call func for the match, and all address matches */
		if (func)
			func(match, data);

		if (match->addr.section != SHN_UNDEF)
			return __for_each_addr(match, func, data) + 1;

		return 1;
	}

	return 0;
}

static void set_crc(struct symbol *sym, void *data)
{
	unsigned long *crc = data;

	if (sym->state == SYMBOL_PROCESSED && sym->crc != *crc)
		warn("overriding version for symbol %s (crc %lx vs. %lx)",
		     sym->name, sym->crc, *crc);

	sym->state = SYMBOL_PROCESSED;
	sym->crc = *crc;
}

void symbol_set_crc(struct symbol *sym, unsigned long crc)
{
	if (for_each(sym->name, set_crc, &crc) == 0)
		error("no matching symbols: '%s'", sym->name);
}

static void set_ptr(struct symbol *sym, void *data)
{
	sym->ptr_die_addr = (uintptr_t)((Dwarf_Die *)data)->addr;
}

void symbol_set_ptr(struct symbol *sym, Dwarf_Die *ptr)
{
	if (for_each(sym->name, set_ptr, ptr) == 0)
		error("no matching symbols: '%s'", sym->name);
}

static void set_die(struct symbol *sym, void *data)
{
	sym->die_addr = (uintptr_t)((Dwarf_Die *)data)->addr;
	sym->state = SYMBOL_MAPPED;

Annotation

Implementation Notes