/*
 * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH,
 *                    IBM Corporation
 */
#include <lcrash.h>

/*
 * module_banner()
 */
void
module_banner(FILE *ofp, int flags)
{
	if(flags & C_FULL){
		print_banner(ofp, "EXPORTED MODULE SYMBOLS: %}75", flags);
	} else {
		print_banner(ofp, "%>      ADDR%      SIZE USED NAME"
			     "                          REFS %}75", flags);
	}
}

/*
 * print_module()
 */
void
print_module(kaddr_t addr, void *ptr, int flags, FILE *ofp)
{
	long dummy;
	void *dump_page = NULL;

	dump_page = kl_alloc_block(dump_page_size, K_TEMP);
	if (dump_page) {
		memset(dump_page, 0, dump_page_size);
		GET_BLOCK(kl_kaddr(ptr, "module", "name"),
			  dump_page_size, dump_page);
	}

	if(flags & C_FULL){
		if(*(char*) dump_page == '\000') {
			fprintf(ofp, "        Module: %s\n",
				KL_KERNEL_MODULE);
		} else {
			fprintf(ofp, "        Module: %s\n",
				(char *) dump_page);
		}
		print_modsyms(ptr, ofp);
	} else {
		print_value(ofp, "", ADDR64(addr), 8, ADDR_FLG);
		print_value(ofp, " ", UINT64(KL_UINT(ptr, "module", "size")),
			    9, UNSIGNED_FLG);
		dummy = KL_INT(ptr, "module", "uc");
		print_value(ofp, " ", *(int*)&dummy, 4, 0);
		if(*(char*) dump_page == '\000') {
			fprintf(ofp, " %-30s", KL_KERNEL_MODULE);
		} else {
			fprintf(ofp, " %-30s", (char *) dump_page);
		}
		print_modrefs(ptr, (char *)dump_page, ofp);
	}
	fprintf(ofp, "\n");

	kl_free_block(dump_page);
}

/*
 * print_modrefs()
 */
void
print_modrefs(void *dump_module, char * modname,  FILE *ofp)
{
	long dummy;
	void *dump_ref = NULL;
	size_t size_ref = 0, size_module;
	kaddr_t next_ref = 0;
	int counter = 0;

	size_module = MODULE_SZ;
	dummy = 0;
	if(modname){
		next_ref = kl_kaddr(dump_module, "module", "refs");
		fprintf(ofp, "[");
		while(next_ref && CHECK_ITER_THRESHOLD(counter++)){
			memset(modname, 0, dump_page_size);
			if(kl_get_structure(next_ref, "module_ref",
					    &size_ref, &dump_ref)){
				kl_free_block(dump_ref);
				kl_free_block(dump_module);
				return;
			}
			if(kl_get_structure(kl_kaddr(dump_ref, "module_ref",
						     "ref"), "module",
					    &size_module, &dump_module)){
				kl_free_block(dump_ref);
				return;
			}
			GET_BLOCK(kl_kaddr(dump_module, "module", "name"),
				  dump_page_size, modname);
			if(dummy){
				if(KL_PTRSZ==64){
					fprintf(ofp, "\n %64s%s", "\0", 
						(char *) modname);

				} else {
					fprintf(ofp, "\n %56s%s", "\0", 
						(char *) modname);
				}
			} else {
				fprintf(ofp, "%s", (char *) modname);
			}
			dummy=1;
			next_ref = kl_kaddr(dump_ref, "module_ref", "next_ref");
		}
		ITER_THRESHOLD_MSG(ofp, counter-1);
		fprintf(ofp, "]");
	}
	kl_free_block(dump_ref);
}

/*
 * print_modsyms()
 */
void
print_modsyms(void *dump_module, FILE *ofp)
{
	uint64_t value;
	int i;
	size_t nsyms = 0, size_modsym = 0;
	kaddr_t name, syms;
	void *dump_name = NULL, *dump_modsym = NULL;

	dump_name = kl_alloc_block(KL_SYMBOL_NAME_LEN, K_TEMP);
	if(KL_ERROR){
		return;
	}

	syms = kl_kaddr(dump_module, "module", "syms");
	nsyms = KL_UINT(dump_module, "module", "nsyms");
	fprintf(ofp, "        Number of exported symbols: %lu\n\n", 
		(unsigned long) nsyms);

	for(i=0; (i < nsyms) && CHECK_ITER_THRESHOLD(i); i++){
		if(!i){
		        print_banner(ofp, "%>      ADDR% NAME [MODULE]%}75",
				     BANNER|SMINOR);
		}
		memset(dump_name, 0, KL_SYMBOL_NAME_LEN);
		if(kl_get_structure(syms, "module_symbol",
				    &size_modsym, &dump_modsym)){
			kl_free_block(dump_name);
			kl_free_block(dump_modsym);
			return;
		}
		value=KL_UINT(dump_modsym, "module_symbol", "value");
		name=kl_kaddr(dump_modsym, "module_symbol", "name");
		GET_BLOCK(name, KL_SYMBOL_NAME_LEN, dump_name);
		print_value(ofp, "\n", value, 10, ADDR_FLG);
		fprintf(ofp," %-36s", (char *) dump_name);
		memset(dump_name, 0, KL_SYMBOL_NAME_LEN);
		name=kl_kaddr(dump_module, "module", "name");
		GET_BLOCK(name, KL_SYMBOL_NAME_LEN, dump_name);
		if ( * (char *) dump_name != '\000'){
			fprintf(ofp," [%s]", (char *) dump_name);
		}
		else{
			fprintf(ofp," [%s]", KL_KERNEL_MODULE);
		}
		syms += size_modsym;
		if(i == nsyms-1){
			fprintf(ofp,"\n");
		}
	}
	ITER_THRESHOLD_MSG(ofp, i);
	kl_free_block(dump_name);
	kl_free_block(dump_modsym);
	return;
}
