/*
 * Copyright (C) 2000-2003 ASANO Masahiro
 */

#include "def.h"

#define __KERNEL__
#include <linux/module.h>

void
prhead_module()
{
	mprintf(SPTR" S SYMS GSYM EX ISIZE CSIZE "SPTR" "SPTR" "SPTR" NAME\n",
		"ADDR", "INIT", "MOD_CORE", "ARGS");
}

int module_offset_list = OFFSET(struct module, list);

addr_t
print_module(addr, full)
addr_t addr;
int full;
{
	struct module m;

	memread(addr, sizeof(m), &m, "module");
	mprintf(FPTR " ", addr);
	mprintf("%c ",	m.state == MODULE_STATE_LIVE? 'L':
			m.state == MODULE_STATE_COMING? 'C':
			m.state == MODULE_STATE_GOING? 'G': '?');
	mprintf("%4x %4x %2x ", m.num_syms, m.num_gpl_syms, m.num_exentries);
	mprintf("%5lx %5lx ", m.init_size, m.core_size);
	mprintf(FPTR " " FPTR " " FPTR " ", m.init, m.module_core, m.args);
	mprintstr(m.name, sizeof(m.name));
	mprintf("\n");
	if (full) {
#ifdef CONFIG_MODULE_UNLOAD
		mprintf("\texit       " FPTR "\n", m.exit);
#endif /*CONFIG_MODULE_UNLOAD*/
#ifdef CONFIG_KALLSYMS
		mprintf("\tsymtab     " FPTR "\n", m.symtab);
		mprintf("\tnum_symtab %lx\n", m.num_symtab);
		mprintf("\tstrtab     " FPTR "\n", m.strtab);
#endif /*CONFIG_KALLSYMS*/
	}
	return (addr_t)m.list.next;
}

addr_t
getmsyms(addr)
	addr_t addr;
{
	int i;
	struct module m;
	char buf[128];

#ifdef CONFIG_KALLSYMS
	Elf_Sym elfsym;

	memread(addr, sizeof(m), &m, "module");

	for (i = 1; i < m.num_symtab; i++) {
		memread((addr_t)m.symtab + sizeof(m.symtab[0]) * i,
			sizeof(m.symtab[0]), &elfsym, "symtab");
		if (elfsym.st_shndx == SHN_UNDEF ||
		    elfsym.st_name == 0 || elfsym.st_value == 0 ||
		    elfsym.st_info == '?')
			continue;
		memread((addr_t)m.strtab + elfsym.st_name, sizeof(buf), buf,
			"strtab");
		if (*buf == 0)
			continue;
#ifdef DEBUG
		mprintf(" %s=%lx (%c)\n", buf, elfsym.st_value, elfsym.st_info);
#endif
		addsym(buf, elfsym.st_value, elfsym.st_info);
	}

#else /*CONFIG_KALLSYMS*/
	struct kernel_symbol msym;
	int len;

	memread(addr, sizeof(m), &m, "module");

	for (i = 0; i < m.num_syms; i++) {
		memread((addr_t)m.syms + sizeof(msym) * i, sizeof(msym),
			&msym, "module_symbol");
		if (msym.value == 0 || msym.name == 0)
			continue;
		memread((addr_t)msym.name, sizeof(buf), buf, "symbol name");
#ifdef DEBUG
		if (strchr(buf, '/') != 0)
			continue;
#endif
		len = strlen(buf);
		if (len > 10 && buf[len - 10] =='_' && buf[len - 9] == 'R')
			buf[len - 10] = 0;
#ifdef DEBUG
		mprintf(" %s=%lx\n", buf, msym.value);
#endif
		addsym(buf, msym.value, 0);
	}

#endif /*CONFIG_KALLSYMS*/

	return (addr_t)m.list.next;
}
