98 lines
2.6 KiB
C
98 lines
2.6 KiB
C
/*
|
|
* Post-process kernel image and kernel modules for Fast LKM hash loader
|
|
*
|
|
* Copyright (C) 2008-2009 STMicroelectronics Ltd
|
|
*
|
|
* Author(s): Carmelo Amoroso <carmelo.amoroso@st.com>, STMicroelectronics
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* any later version.
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
* Usage: it is called directly by kbuild
|
|
* (see $(rule_ksymhash) defined in scripts/Makefile.ksymhash)
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <sys/mman.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include "elflib.h"
|
|
|
|
static inline
|
|
void compute_exported_hash(const struct elf_info *elf, enum ksymtab_type tp)
|
|
{
|
|
|
|
struct kernel_symbol *sym;
|
|
struct kernel_symbol *start = elf->ksym_tables[tp].start;
|
|
struct kernel_symbol *stop = elf->ksym_tables[tp].stop;
|
|
|
|
for (sym = start; sym < stop; sym++)
|
|
sym->hash_value = gnu_hash(GET_KSTRING(sym, elf->kstr_offset));
|
|
}
|
|
|
|
static void compute_unresolved_hash(struct elf_info *elf)
|
|
{
|
|
|
|
Elf_Sym *sym;
|
|
ksym_hash_t *hash_values = elf->undef_hash.start;
|
|
|
|
if (!hash_values)
|
|
/* .undef.hash section is not present */
|
|
return;
|
|
|
|
for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
|
|
if (sym->st_shndx == SHN_UNDEF) {
|
|
/* undefined symbol */
|
|
if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL &&
|
|
ELF_ST_BIND(sym->st_info) != STB_WEAK)
|
|
continue;
|
|
else {
|
|
/* GLOBAL or WEAK undefined symbols */
|
|
*hash_values = gnu_hash((unsigned char *)
|
|
(elf->strtab + sym->st_name));
|
|
/*
|
|
* The hash_values array stored into the
|
|
* .undef.hash section that is ordered as the
|
|
* undefined symbols of the .symtab
|
|
*/
|
|
hash_values++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
|
|
enum ksymtab_type k;
|
|
struct elf_info info = { };
|
|
|
|
if (!parse_writable_elf(&info, argv[1]))
|
|
exit(1);
|
|
|
|
for (k = KSYMTAB; k < KSYMTAB_ALL; k++)
|
|
if (info.ksym_tables[k].name)
|
|
/* Compute hash value for exported symbols */
|
|
compute_exported_hash(&info, k);
|
|
|
|
compute_unresolved_hash(&info);
|
|
|
|
parse_elf_finish(&info);
|
|
return 0;
|
|
}
|