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 = kcalloc(nsyms, sizeof(struct got_entry), GFP_KERNEL); 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) { nrela = s->sh_size / sizeof(Elf64_Rela); rela = (void *)hdr + s->sh_offset; for (i = 0; i < nrela; ++i) process_reloc_for_got(rela+i, chains, &got->sh_size); } /* Free the memory we allocated. */ for (i = 0; i < nsyms; ++i) { struct got_entry *g, *n; for (g = chains[i].next; g ; g = n) { n = g->next; kfree(g); } } kfree(chains); return 0; }
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; 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 = kcalloc(nsyms, sizeof(struct got_entry), GFP_KERNEL); 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; for (s = sechdrs; s < esechdrs; ++s) if (s->sh_type == SHT_RELA) { nrela = s->sh_size / sizeof(Elf64_Rela); rela = (void *)hdr + s->sh_offset; for (i = 0; i < nrela; ++i) process_reloc_for_got(rela+i, chains, &got->sh_size); } for (i = 0; i < nsyms; ++i) { struct got_entry *g, *n; for (g = chains[i].next; g ; g = n) { n = g->next; kfree(g); } } kfree(chains); return 0; }