arch/alpha/kernel/module.c

Source file repositories/reference/linux-study-clean/arch/alpha/kernel/module.c

File Facts

System
Linux kernel
Corpus path
arch/alpha/kernel/module.c
Extension
.c
Size
6963 bytes
Lines
272
Domain
Architecture Layer
Bucket
arch/alpha
Inferred role
Architecture Layer: implementation source
Status
source 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 got_entry {
	struct got_entry *next;
	Elf64_Sxword r_addend;
	int got_offset;
};

static inline void
process_reloc_for_got(Elf64_Rela *rela,
		      struct got_entry *chains, Elf64_Xword *poffset)
{
	unsigned long r_sym = ELF64_R_SYM (rela->r_info);
	unsigned long r_type = ELF64_R_TYPE (rela->r_info);
	Elf64_Sxword r_addend = rela->r_addend;
	struct got_entry *g;

	if (r_type != R_ALPHA_LITERAL)
		return;

	for (g = chains + r_sym; g ; g = g->next)
		if (g->r_addend == r_addend) {
			if (g->got_offset == 0) {
				g->got_offset = *poffset;
				*poffset += 8;
			}
			goto found_entry;
		}

	g = kmalloc_obj(*g);
	g->next = chains[r_sym].next;
	g->r_addend = r_addend;
	g->got_offset = *poffset;
	*poffset += 8;
	chains[r_sym].next = g;

 found_entry:
	/* Trick: most of the ELF64_R_TYPE field is unused.  There are
	   42 valid relocation types, and a 32-bit field.  Co-opt the
	   bits above 256 to store the got offset for this reloc.  */
	rela->r_info |= g->got_offset << 8;
}

int
module_frob_arch_sections(Elf64_Ehdr *hdr, Elf64_Shdr *sechdrs,
			  char *secstrings, struct module *me)
{
	struct got_entry *chains;
	Elf64_Rela *rela;
	Elf64_Shdr *esechdrs, *symtab, *s, *got;
	unsigned long nsyms, nrela, i;

	esechdrs = sechdrs + hdr->e_shnum;
	symtab = got = NULL;

	/* Find out how large the symbol table is.  Allocate one got_entry
	   head per symbol.  Normally this will be enough, but not always.
	   We'll chain different offsets for the symbol down each head.  */
	for (s = sechdrs; s < esechdrs; ++s)
		if (s->sh_type == SHT_SYMTAB)
			symtab = s;
		else if (!strcmp(".got", secstrings + s->sh_name)) {
			got = s;
			me->arch.gotsecindex = s - sechdrs;
		}

	if (!symtab) {
		printk(KERN_ERR "module %s: no symbol table\n", me->name);
		return -ENOEXEC;
	}
	if (!got) {
		printk(KERN_ERR "module %s: no got section\n", me->name);
		return -ENOEXEC;
	}

	nsyms = symtab->sh_size / sizeof(Elf64_Sym);
	chains = kzalloc_objs(struct got_entry, nsyms);
	if (!chains) {
		printk(KERN_ERR
		       "module %s: no memory for symbol chain buffer\n",
		       me->name);
		return -ENOMEM;
	}

	got->sh_size = 0;
	got->sh_addralign = 8;
	got->sh_type = SHT_NOBITS;

	/* Examine all LITERAL relocations to find out what GOT entries
	   are required.  This sizes the GOT section as well.  */
	for (s = sechdrs; s < esechdrs; ++s)
		if (s->sh_type == SHT_RELA) {

Annotation

Implementation Notes