dbgif_exe.c 3.64 KB
#include <elf.h>
#include <stdio.h>
#include <stdlib.h>
#include "rkapi.h"
#include "dbgproto.h"

Elf32_Ehdr ELFheader;
Elf32_Phdr progHeader;
extern int currentFD;
KKNumberEvent countReply;

int GetExeRegions( KKHeader * packet, char * filename, int isGetRegions )
{
	FILE * exe;
	register int numRegions = 0, regionsRead;
	KKRegion * regions;
	KKObjectEvent * request = (KKObjectEvent *) packet;

	if ( filename == NULL )	/* as it always is... */
	{
		if ( packet->method == 0 )
			filename = "/usr/tv/debug/rmon.tvd";
		else
			filename = "/usr/tv/debug/imem.tvd";
	}
	if ( (exe = fopen( filename, "r" )) == NULL )
		return 0;
	if ( fread( &ELFheader, sizeof( Elf32_Ehdr ), 1, exe ) != 1 )
	{
		fprintf( stderr, "Read ELF header failed in %s\n", filename );
		return 0;
	}
	if (    (ELFheader.e_ident[0] != 0x7f) ||
                (ELFheader.e_ident[1] != 'E') ||
                (ELFheader.e_ident[2] != 'L') ||
                (ELFheader.e_ident[3] != 'F') )
        {
                fprintf( stderr, "%s is not an ELF file\n", filename );
 		return 0;
	}
	
	/* Count loadable sections */

	fseek( exe, ELFheader.e_phoff, SEEK_SET );
	for ( regionsRead = 0; regionsRead < ELFheader.e_phnum; ++regionsRead )
	{
		if ( fread( &progHeader, sizeof( Elf32_Phdr ), 1, exe ) != 1 )
		{
			fprintf( stderr, "Read prog header failed in %s\n", filename );
			break;
		}
		if ( progHeader.p_type != PT_LOAD )
			continue;
		++numRegions;
	}
	if ( packet->method == 0 )
		numRegions += 3;	/* Add fake sections */

	/* if we only wanted a count, we are done. Otherwise, read them
		again and return their contents */

	if ( isGetRegions )
	{
		int replySize = sizeof( KKRegionEvent ) + 
			(numRegions - 1) * sizeof( KKRegion );
		KKRegionEvent * reply;

		reply = (KKRegionEvent *) malloc( replySize );
		fseek( exe, ELFheader.e_phoff, SEEK_SET );
		regions = reply->regions;
		for ( regionsRead = 0; regionsRead < ELFheader.e_phnum; ++regionsRead )
		{
			if ( fread( &progHeader, sizeof( Elf32_Phdr ), 1, exe ) != 1 )
			{
				fprintf( stderr, "Read prog header failed in %s\n", filename );
				break;
			}
			if ( progHeader.p_type != PT_LOAD )
				continue;
			regions->vaddr = progHeader.p_vaddr;
			regions->size = progHeader.p_memsz;
			regions->flags = 0;
			if ( progHeader.p_flags & PF_R )
				regions->flags |= KK_READ;
			if ( progHeader.p_flags & PF_W )
				regions->flags |= KK_WRITE;
			if ( progHeader.p_flags & PF_X )
				regions->flags |= KK_EXEC;
			regions->paddr = progHeader.p_paddr;
			++regions;
		}

		/* Add regions for IMEM and DMEM and IPOS */

		if ( packet->method == 0 )
		{
			regions->vaddr = regions->paddr = 0x4001000;
			regions->size = 0x1000;
			regions->flags = KK_READ | KK_WRITE;
			++regions;
			regions->vaddr = regions->paddr = 0x4000000;
			regions->size = 0x1000;
			regions->flags = KK_READ | KK_WRITE;
			++regions;
			regions->vaddr = regions->paddr = 0x88000000;
			regions->size = 0x20000;
			regions->flags = KK_READ | KK_WRITE | KK_EXEC;
		}

		reply->header.code = request->header.code;
		reply->header.error = TV_ERROR_NO_ERROR;
		reply->header.length = replySize;
		reply->header.rev = 2;
		reply->header.type = _KK_REPLY;
		reply->object = request->object;
		reply->number = numRegions;		
		prEvent( reply );
		send( currentFD, reply, replySize, 0 );
		free( reply );
	}
	else
	{
		countReply.header.code = request->header.code;
		countReply.header.error = TV_ERROR_NO_ERROR;
		countReply.header.length = sizeof( KKNumberEvent );
		countReply.header.rev = 2;
		countReply.header.type = _KK_REPLY;
		countReply.object = request->object;
		countReply.number = numRegions;
		prEvent( &countReply );
		send( currentFD, &countReply, sizeof( KKNumberEvent ), 0 );
	}
	fclose( exe );
}