/****************************************************************************
**
**  Name:  LSECTION.C
**
**  Description:
**      Process section part of ELF binary file.
*****************************************************************************/
                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/
#include <io.h>

#ifndef __LDR__
#include "ldr.h"
#endif

#ifndef _HEAP_
#include "heap.h"
#endif

#ifndef _SYMBLSVR_
#include "symblsvr.h"
#endif

#ifndef __ERR__
#include "err.h"
#endif

#ifndef __LDEBUG__
#include "ldebug.h"
#endif

#ifndef __LPROFILE__
#include "lprofile.h"
#endif

                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/
Elf32_Shdr *section_info[MAX_SECTIONS+3]; /* Added 3 more for default sections */
Elf32_Phdr *execution_info[10];
U32 DebugOffset, LineOffset;
U32 LineSize, DebugSize;

U16 nSections, codeSecIndex, dataSecIndex, rtaSecIndex;
U16 nExecutions;
BOOLEAN findCode, findData, findRTA;
BOOLEAN mergeSections;
                       /****************************
                        *                          *
                        *    EXTERNAL VARIABLES    *
                        *                          *
			****************************/
extern BOOLEAN hasStackInfo;
extern CHAR errbuf[];
extern HDR695 Hdr695;
extern U32 stackTop, stackSize;
extern CHAR sectionNames[MAX_NUM_SECTION_NAMES][SIZE_SECTION_NAME];
extern CHAR pwrViewsDir[];
extern BOOLEAN useDefaultSection;
extern Elf32_Endr HdrELF;

extern U32 symtab_offset, symtab_size;
extern U32 strtab_offset, strtab_size;
//Hera 2/2/98
extern U32 sfname_offset, sfname_size;
extern U32 srcinfo_offset, srcinfo_size;
//Hera

                       /****************************
                        *                          *
                        *     LOCAL PROTOTYPES     *
                        *                          *
                        ****************************/
RETCODE PRIVATE PSGetSection(CHAR *, U16 *);
RETCODE PRIVATE GetSectionInfo(Elf32_Shdr *, HANDLE);
RETCODE PRIVATE GetExecutionInfo(Elf32_Phdr *, HANDLE);
RETCODE PRIVATE PSGetStack(HANDLE, U32, U32, U32, U32);

                       /****************************
			*                          *
                        *      EXECUTABLE CODE     *
                        *                          *
                        ****************************/

/******************************************************************************
**
**  ProcessSecPart
**
******************************************************************************/
RETCODE ProcessSecPart(HANDLE hfile, U16 *version, U16 symflag) {
   Elf32_Shdr *psection;
   U16 index=0;     /* number of sections processed */
   RETCODE err;
   U16 size;
   char *shstr,*string;
   BASE_TYPE basetype;

   /* first, seek to Section Part of file */
   if (SeekELFFile(hfile, HdrELF.e_shoff, SEEK_SET) == -1L)
      return (ER_BAD_SEEK);

   nSections = HdrELF.e_shnum; /*the section number*/
   while (index < nSections) {
      if ((psection = (Elf32_Shdr *)TMalloc(sizeof(Elf32_Shdr))) == NULL) {
	 return(ER_NO_MEMORY);
      }
      if ((err = GetSectionInfo(psection, hfile)) != GOOD) {
         TFree((LPSTR)psection);
         return(err);
      }

      section_info[index++] = psection;
      if (index == MAX_SECTIONS) {
         // 02/24/94 - Nghia
         // Bruce requested to remove this warning message
	 // Warning(ER_TOOMANY_SEC);
         break; /* Discard the the remaining sections */
      }
   }  /* while */

   //Get section name
   size = (U16)section_info[HdrELF.e_shstrndx]->sh_size;
   if ((shstr = (char *)TMalloc(size)) == NULL) {
	 return(ER_NO_MEMORY);
    }

   /*goto section header string (.shstrtab)*/
   SeekELFFile(hfile,section_info[HdrELF.e_shstrndx]->sh_offset,SEEK_SET);
   _lread(hfile, shstr, size);

   for(index = 0; index < nSections; index++)
   {
     string = shstr+section_info[index]->sh_name;
     strcpy((section_info[index]->sec_name),string);

     //if section_info[index]->sh_addr = 0x00, the section does not loaded
     //to memory, it is only an infomation.
     if(symflag && section_info[index]->sh_addr)
     {
        basetype = BASE_UNKNOWN;
        if((section_info[index]->sh_flags & 0x4) == 0x4) //SHF_EXECINSTR = 0x4
	    basetype = basetype + BASE_CODE;
        if((section_info[index]->sh_flags & 0x1) == 0x1) //SHF_WRITE = 0x1
	    basetype = basetype + BASE_DATA;

        if (SymAddBaseCreate((LPSTR)section_info[index]->sec_name,
                              index, 0L, basetype) != GOOD) //baseaddress=0L
	    Warning(ER_SYMBASE);
     }

     if (strcmp(string,".debug") == 0){
        *version = 1;
        DebugOffset = section_info[index]->sh_offset;
        DebugSize = section_info[index]->sh_size;
     }
     else if(strcmp(string,".debug_info") == 0){
        *version = 2;
        DebugOffset = section_info[index]->sh_offset;
        DebugSize = section_info[index]->sh_size;
     }
     else if(!strcmp(string,".line")){
        LineOffset = section_info[index]->sh_offset;
        LineSize = section_info[index]->sh_size;
     }

     else if(!strcmp(string,".symtab")){
        symtab_offset = section_info[index]->sh_offset;
        symtab_size = section_info[index]->sh_size;
     }
     else if(!strcmp(string,".strtab")){
        strtab_offset = section_info[index]->sh_offset;
        strtab_size = section_info[index]->sh_size;
     }
     //Hera 2/2/98
     else if(!strcmp(string,".debug_sfnames")) {
	sfname_offset = section_info[index]->sh_offset;
        sfname_size = section_info[index]->sh_size;
     }
     else if(!strcmp(string,".debug_srcinfo")) {
	srcinfo_offset = section_info[index]->sh_offset;
	srcinfo_size = section_info[index]->sh_size;
     }//Hera
   }
   TFree(shstr);
   if ((err=PSGetSection(&sectionNames[CODE_SECT][0], &codeSecIndex)) != GOOD)
       return(err);

   if ((err=PSGetSection(&sectionNames[DATA_SECT][0], &dataSecIndex)) != GOOD)
	return(err);

   PSGetStack(hfile,symtab_offset, symtab_size, strtab_offset, strtab_size);
   /* Save the number of sections */
DoneProcessSections:
   return(GOOD);
}  /* ProcessSecPart */

RETCODE PRIVATE PSGetStack(HANDLE hfile, U32 symtab_offset, U32 symtab_size,
					 U32 strtab_offset, U32 strtab_size)
{
   char* Name;
   char* ptrName;     // Judy 7/3/97
   U32 index,stackEnd,stackInit;
   U32 init,end;
   RETCODE err = GOOD;

   if(!strtab_size || !symtab_size)
     return GOOD;

   err = SeekELFFile(hfile, strtab_offset, SEEK_SET);
   Name = (char *) TMalloc(strtab_size);
   ptrName=Name;      // Judy 7/3/97
   GetELFBytes(hfile, Name, strtab_size);
   init = end = index = 0;
   while(strtab_size > index)
   {
     if(!strcmp(Name,"__SP_INIT") && !init)
        init = index;
     else if(!strcmp(Name,"__SP_END") && !end)
	end = index;
     index += strlen(Name)+1;
     Name += strlen(Name)+1;
   }

   TFree(ptrName);            // Judy 7/3/97
   if(init == 0 && end == 0)
   {
      //stackTop = 0;
      //stackSize = 0x800;    //default = 0x800;
      return GOOD;
   }
   hasStackInfo = TRUE;
   err = SeekELFFile(hfile,symtab_offset, SEEK_SET);
   while(symtab_size)
   {
     U32 Value;
     Value = GetELFU32(hfile);
     if(Value == init)
     {
       stackInit = GetELFU32(hfile);
       SeekELFFile(hfile,8,SEEK_CUR);
     }
     else if(Value == end)
     {
       stackEnd = GetELFU32(hfile);
       SeekELFFile(hfile,8,SEEK_CUR);
     }
     else
       SeekELFFile(hfile,12,SEEK_CUR);
     symtab_size -= sizeof(Elf32_Sym);
   }
   if(stackEnd < stackInit)
   { 
      stackSize = stackInit - stackEnd;
      stackTop = stackEnd;
   }
   else
   {
      stackSize = stackEnd - stackInit;
      stackTop = stackInit;
   }   
   return err;
}


/******************************************************************************
**
**  FreeSections - free memory associated with section info struct
**
******************************************************************************/
RETCODE FreeSections(U16 numSection) {
   LOOP_VAR i;

   for (i = 0; i < numSection; i++) {
      if (TFree((LPSTR)section_info[i]) != GOOD) {
         Warning(ER_BAD_FREE);
         return(ER_BAD_FREE);
      }
   }
   nSections = codeSecIndex = dataSecIndex = rtaSecIndex = 0;
   findCode = findData = findRTA = FALSE;
   DebugOffset = LineOffset = 0;
   sfname_offset = srcinfo_offset = 0;//Hera 2/2/98
   LineSize = 0;
   return(GOOD);
}  /* FreeSections */

/******************************************************************************
**
**  PSGetCode - Get core region
**
******************************************************************************/
RETCODE PSGetCode(U32 *pstartAddr, U32 *prange) {
   U16 indexVars;
   RETCODE err;

   *pstartAddr = RANGE_NOT_SET;
   *prange = 0L;
   if ((err = FindBaseCodeIndex(&indexVars)) != GOOD)
      return(err);
   *pstartAddr = section_info[indexVars]->sh_addr;
   *prange = section_info[indexVars]->sh_size;
   return(GOOD);
}  /* PSGetCode */

/******************************************************************************
**
**  PSGetData - Get load region for data
**
******************************************************************************/
RETCODE PSGetData(U32 *pstartAddr, U32 *prange) {
   U16 indexVars;
   RETCODE err;

   /* Get array index for sections */
   *pstartAddr = RANGE_NOT_SET;
   *prange = 0L;
   if ((err = FindBaseDataIndex(&indexVars)) != GOOD) {
      return(err);
   }
   *pstartAddr = section_info[indexVars]->sh_addr;
   *prange = section_info[indexVars]->sh_size;
   return(GOOD);
}  /* PSGetData */

/******************************************************************************
**
**  PSGetSection - get index of section in section_info table
**
******************************************************************************/
RETCODE PRIVATE PSGetSection(CHAR *secname, U16 *index) {
   U16 i;

   *index = 0;
   for (i = 0; i < nSections; i++) {
      if (stricmp(section_info[i]->sec_name, secname) == 0) {
         *index = i;
         return (GOOD);
      }
   }
   return(ER_SECTION_NOT_FOUND);
}  /* PSGetSection */


/******************************************************************************
**
**  GetSectionInfo - retrieve section information from loadfile
**
******************************************************************************/
RETCODE PRIVATE GetSectionInfo(Elf32_Shdr *psection, HANDLE hfile) {
   RETCODE err = GOOD;

   psection->sh_name = GetELFU32(hfile);
   psection->sh_type = GetELFU32(hfile);
   psection->sh_flags = GetELFU32(hfile);
   psection->sh_addr = GetELFU32(hfile);
   psection->sh_offset = GetELFU32(hfile);
   psection->sh_size = GetELFU32(hfile);
   psection->sh_link = GetELFU32(hfile);
   psection->sh_info = GetELFU32(hfile);
   psection->sh_addralign = GetELFU32(hfile);
   psection->sh_entsize = GetELFU32(hfile);

   return(err);
}

RETCODE ProcessExecPart(HANDLE hfile)
{
  RETCODE err;
  int index;
  Elf32_Phdr *pexecution;

  index = 0;

  nExecutions = HdrELF.e_phnum;

  SeekELFFile(hfile, HdrELF.e_phoff, SEEK_SET);

  while (index < nExecutions) {
      if ((pexecution = (Elf32_Phdr *)TMalloc(sizeof(Elf32_Phdr))) == NULL) {
	 return(ER_NO_MEMORY);
      }
      if ((err = GetExecutionInfo(pexecution, hfile)) != GOOD) {
         TFree((LPSTR)pexecution);
         return(err);
      }
      execution_info[index++] = pexecution;
      if (index == 10) 
         break; /* Discard the the remaining sections */
   }  /* while */
  return GOOD;
}

RETCODE GetExecutionInfo(Elf32_Phdr* pexecution, HANDLE hfile)
{
  RETCODE err = GOOD;

  pexecution->p_type = GetELFU32(hfile);
  pexecution->p_offset = GetELFU32(hfile);
  pexecution->p_vaddr = GetELFU32(hfile);
  pexecution->p_paddr = GetELFU32(hfile);
  pexecution->p_filesz = GetELFU32(hfile);
  pexecution->p_memsz = GetELFU32(hfile);
  pexecution->p_flags = GetELFU32(hfile);
  pexecution->p_align = GetELFU32(hfile);

  return err;
}

/******************************** E O F ***********************************/
