coff.c 5.58 KB
/*
 * coff.c:	routines to read contents of a coff file into a buffer for 
 * 		subsequent download to the ultra64 development system.
 *
 *		Cloned from an OS conversion utility suite
 *
 * Copyright 1995, Silicon Graphics, Inc.
 * All Rights Reserved.
 *
 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
 * the contents of this file may not be disclosed to third parties, copied or
 * duplicated in any form, in whole or in part, without the prior written
 * permission of Silicon Graphics, Inc.
 *
 * RESTRICTED RIGHTS LEGEND:
 * Use, duplication or disclosure by the Government is subject to restrictions
 * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
 * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
 * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
 * rights reserved under the Copyright Laws of the United States.
 *
 * $Revision: 1.2 $
 */

#include <stdio.h>
#ifdef __sgi__
#include "sex.h"
#include "sym.h"
#include "cmplrs/stsupport.h"
#include "filehdr.h"
#include "ldfcn.h"
#include "scnhdr.h"
#else
#include "sym.h"
#include "ecoff.h"
#include "mips.h"
#endif

// Function prototypes for internal functions
//
static int Extract(unsigned int *buf);

// Global variables
//
unsigned int Address;                   /* Address being Dumped.    */
unsigned int Data0;                     /* Data being Dumped.       */
unsigned int Data1;                     /* Data being Dumped.       */
int      Swap   = 0;                    /* Swap Text Words.         */
char    *OFileName;                     /* Object File To Dump.     */
char    *AFileName;                     /* ASCII File To Dump into. */
char    *SName;                         /* Section to Dump.         */
#ifdef __sgi__
LDFILE  *LDPtr;                         /* File's ld Pointer.       */
SCNHDR   SHeader;                       /* Section Header.          */
FILE    *AFile;                         /* ASCII File.              */
#endif


////////////////////////////////////////////////////////////////////////////////
// readCoff()
//
// Read a COFF file into a buffer.  Return number of bytes read,
// -1 if error.
//
int readCoff(char *fname, unsigned int *buf) {
  int textSize, dataSize, bssSize;
  
  OFileName = fname;
  SName     = ".text";	/* set section name = .text */
  textSize = Extract(buf);
  
  if (textSize < 0)
    return(-1);
  
  /*
   * Ignore .data & .bss; we would have to decide where to put them if we
   * needed to use them, but these short-lived bootstrap modules won't need
   * data or bss, so punt.
   */
#ifdef NOTDEF
  OFileName = fname;
  SName     = ".data";	/* set section name = .data */
  dataSize = Extract( ((unsigned int *)((int)buf + textSize)) );
  
  if (dataSize != 0)
    return(-1);
  
  OFileName = fname;
  SName     = ".bss";	/* set section name = .text */
  bssSize = Extract( ((unsigned int *)((int)buf + (textSize + dataSize))) );
  
  if (bssSize < 0)
    return(-1);
  return( (textSize + dataSize + bssSize) );
#endif
  return( textSize );
}


////////////////////////////////////////////////////////////////////////////////
// Extract()
//
//
//
static int Extract(unsigned int *buf) {
  int bytesRead = -1;
  
#ifndef __sgi__
  FILE *fp;
  FILHDR hdr;
  SCNHDR scn;
  int n, i;
  unsigned short magic;
  if ((fp = fopen(OFileName, "r")) == NULL) {
    fprintf(stderr, "Extract(): Cannot open %s.\n", OFileName);
    return -1;
  }
  fread(&hdr, sizeof hdr, 1, fp);
  magic = hdr.f_magic[1] | hdr.f_magic[0] << 8;
  switch (magic) 
    {
    case MIPS_MAGIC_BIG:
    case MIPS_MAGIC_BIG2:
    case MIPS_MAGIC_BIG3:
#if 0
      Swap = (gethostsex () == LITTLEENDIAN);
#endif
      break;
      
    case MIPS_MAGIC_LITTLE:
    case MIPS_MAGIC_LITTLE2:
    case MIPS_MAGIC_LITTLE3:
#if 0
      Swap = (gethostsex () == BIGENDIAN);
#endif
      break;
    }
  /* skip aout header */
  fseek(fp, sizeof(AOUTHDR), SEEK_CUR);
  n = ntohs(hdr.f_nscns[0] | hdr.f_nscns[1] << 8);
  for(i = 0; i < n; i++) {
    fread(&scn, sizeof scn, 1, fp);
    if (strcmp(scn.s_name, SName) == 0) {
      fseek(fp, ntohl(scn.s_scnptr[0] | scn.s_scnptr[1] << 8 | scn.s_scnptr[2] << 16 | scn.s_scnptr[3] << 24), SEEK_SET);
      bytesRead = fread(buf, 1, ntohl(scn.s_size[0] | scn.s_size[1] << 8 | scn.s_size[2] << 16 | scn.s_size[3] << 24), fp);
      break;
    }
  }
  fclose(fp);
  return bytesRead;
#else
  if ((LDPtr = (LDFILE *) ldopen (OFileName, NULL)) == NULL)
    {                                   /* Open File.               */
      fprintf (stderr, "Extract(): Cannot open %s.\n", OFileName);
      return (-1);
    }
  
  switch (HEADER (LDPtr).f_magic) 
    {
    case MIPSEBMAGIC:
    case MIPSEBMAGIC_2:
    case MIPSEBMAGIC_3:
      Swap = (gethostsex () == LITTLEENDIAN);
      break;
      
    case MIPSELMAGIC:
    case MIPSELMAGIC_2:
    case MIPSELMAGIC_3:
      Swap = (gethostsex () == BIGENDIAN);
      break;
    }
  if (ldnshread (LDPtr, SName, &SHeader) == FAILURE)
    {
#ifdef NO_HUSH
      fprintf (stderr, "Warning:  %s has no %s section.\n", OFileName, SName);
#endif
    } else {
      
      FSEEK (LDPtr, SHeader.s_scnptr, BEGINNING);
      
      for (Address = SHeader.s_paddr; 
	   (Address - SHeader.s_paddr) < SHeader.s_size; Address += 8) {
	FREAD ((char *)&Data0, 1, 4, LDPtr);
	if (Swap) Data0 = swap_word (Data0);
	FREAD ((char *)&Data1, 1, 4, LDPtr);
	if (Swap) Data1 = swap_word (Data1);
	if (Swap) {
	  *buf = Data1;
	  *(buf+1) = Data0;
	} else {
	  *buf = Data0;
	  *(buf+1) = Data1;
	}
	buf += 2;
      }
    }
  ldclose (LDPtr);                    /* Close File.              */
  return(SHeader.s_size);		/* # of bytes read */
#endif
}