📄 elf.c
字号:
/*********************************************************************
*
* Copyright:
* MOTOROLA, INC. All Rights Reserved.
* You are hereby granted a copyright license to use, modify, and
* distribute the SOFTWARE so long as this entire notice is
* retained without alteration in any modified and/or redistributed
* versions, and that such modified versions are clearly identified
* as such. No licenses are granted by implication, estoppel or
* otherwise under any patents or trademarks of Motorola, Inc. This
* software is provided on an "AS IS" basis and without warranty.
*
* To the maximum extent permitted by applicable law, MOTOROLA
* DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING
* IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
* PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH REGARD TO THE
* SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF) AND ANY
* ACCOMPANYING WRITTEN MATERIALS.
*
* To the maximum extent permitted by applicable law, IN NO EVENT
* SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING
* WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS
* INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY
* LOSS) ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
*
* Motorola assumes no responsibility for the maintenance and support
* of this software
********************************************************************/
/*
* File: elf.c
* Purpose: Data definitions and routines for downloading ELF files.
*
* Notes:
*
*
* Modifications:
* 06-17-99 EJD Use Section Headers rather than Program Headers
*
*/
/*#include "dbug.h"
#include "libdbug.h"*/
#include "elf.h"
#include "example.h"
#include "util.h"
DataFunctions fileAccessFunctions;
/********************************************************************/
#define MAX_FILENAME 13
#define ET_EXEC 2
#define EM_MIPS 8
#define EV_CURRENT 1
#define SHT_NULL 0
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
#define SHT_RELA 4
#define SHT_NOBITS 8
#define EI_IDENT_PAD_SIZE 9
#define ELF_MAX_HDR 30
// #define DEBUG_MSG 1
typedef uint32 Elf32_Addr;
typedef uint32 Elf32_Word;
typedef uint16 Elf32_Half;
typedef uint32 Elf32_Off;
typedef int32 Elf32_Sword;
typedef struct
{
unsigned char EI_MAG[4];
uint8 EI_CLASS;
uint8 EI_DATA;
uint8 EI_VERSION;
unsigned char EI_PAD[EI_IDENT_PAD_SIZE];
} Elf32_Ident;
typedef struct
{
Elf32_Ident e_ident;
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry;
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} Elf32_Ehdr;
typedef struct
{
Elf32_Word p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
Elf32_Word p_filesz;
Elf32_Word p_memsz;
Elf32_Word p_flags;
Elf32_Word p_align;
} Elf32_Phdr;
typedef struct
{
Elf32_Word sh_name;
Elf32_Word sh_type;
Elf32_Word sh_flags;
Elf32_Addr sh_addr;
Elf32_Off sh_offset;
Elf32_Word sh_size;
Elf32_Word sh_link;
Elf32_Word sh_info;
Elf32_Word sh_addralign;
Elf32_Word sh_entsize;
} Elf32_Shdr;
typedef struct
{
Elf32_Addr r_offset;
Elf32_Word r_info;
Elf32_Sword r_addend;
} Elf32_Rel;
typedef struct
{
Elf32_Word st_name;
Elf32_Addr st_value;
Elf32_Word st_size;
unsigned char st_info;
unsigned char st_other;
Elf32_Half st_shndx;
} Elf32_Sym;
/********************************************************************/
static volatile int elfBytesRead;
static int symndx, strndx;
static Elf32_Ehdr elfhdr;
static Elf32_Shdr scnhdr[ELF_MAX_HDR];
static uint32 scn_foffset;
static char elfFileName[MAX_FILENAME];
static volatile int progress;
static dots;
static uint32 startadd;
/********************************************************************/
static int
elfRead (void *buffer, int bytes)
{
#ifdef DEBUG_MSG
if(bytes > 1){
printf("\n elfRead: buffer address is %x", buffer);
printf("\tsize is %d ", bytes);
}
#endif
int bytesRead = fileAccessFunctions.read(buffer, bytes);
#ifdef DEBUG_MSG
if(bytes > 1){
printf("\tbytesRead is %d ", bytesRead);
}
#endif
elfBytesRead += bytesRead;
updateProgress(bytesRead);
return bytesRead;
}
static int
elfRead2 (void *buffer, int bytes, uint32 offset)
{
#ifdef DEBUG_MSG
printf("\n elfRead2: buffer address is %x", buffer);
printf(" size is %x ", bytes);
printf(" Flash offset is %x", offset);
#endif
memCopy((void *)(startadd + offset), buffer, bytes); //src, dest, bytes
elfBytesRead += bytes;
updateProgress(bytes);
return bytes;
}
static int
elfOpen(const char* fileName)
{
elfBytesRead = 0;
return fileAccessFunctions.open(fileName);
}
void elfClose()
{
fileAccessFunctions.close();
}
/********************************************************************/
static int
elfReadSectionData()
{
char ch;
char* address;
int i;
// get the start address
startadd = stringToInt(elfFileName);
for(i = 0; i < elfhdr.e_shnum; ++i)
{
while(elfBytesRead < scnhdr[i].sh_offset) //seek to beginning of section
elfRead(&ch, 1);
switch (scnhdr[i].sh_type)
{
case SHT_NULL:
break;
case SHT_PROGBITS:
address = (char *)scnhdr[i].sh_addr;
if (address && scnhdr[i].sh_size)
if(!elfRead2(address, scnhdr[i].sh_size, scnhdr[i].sh_offset))
return 0;
break;
case SHT_SYMTAB:
break;
case SHT_STRTAB:
break;
case SHT_RELA:
break;
case SHT_NOBITS:
address = (char *)scnhdr[i].sh_addr;
if(address && scnhdr[i].sh_size)
memFill(address, scnhdr[i].sh_size, 0x00); //zero memory
break;
default:
/* unknown section type */
break;
}
}
}
void displaySectionHeader(Elf32_Shdr* header)
{
printf(" sh_name: %08X\n",header->sh_name);
printf(" sh_type: %08X\n",header->sh_type);
printf(" sh_flags: %08X\n",header->sh_flags);
printf(" sh_addr: %08X\n",header->sh_addr);
printf(" sh_offset: %08X\n",header->sh_offset);
printf(" sh_size: %08X\n",header->sh_size);
printf(" sh_link: %08X\n",header->sh_link);
printf(" sh_info: %08X\n",header->sh_info);
printf(" sh_addalgn: %08X\n",header->sh_addralign);
printf(" sh_entsize: %08X\n",header->sh_entsize);
}
/********************************************************************/
static int
elfReadSectionHeader()
{
int i;
char c;
scn_foffset = (uint32)~0;
symndx = -1;
strndx = -1;
if (!elfhdr.e_shnum)
return 0;
for(i = elfBytesRead; i < elfhdr.e_shoff; ++i) //seek to header
if(!elfRead(&c, 1))
return 0;
for (i = 0; i < elfhdr.e_shnum; ++i)
{
elfRead(&scnhdr[i], sizeof(Elf32_Shdr));
// displaySectionHeader(&scnhdr[i]);
switch (scnhdr[i].sh_type)
{
case SHT_NULL:
break;
case SHT_PROGBITS:
if (scnhdr[i].sh_offset < scn_foffset)
scn_foffset = scnhdr[i].sh_offset;
break;
case SHT_SYMTAB:
if (symndx < 0)
symndx = i;
if (scnhdr[i].sh_offset < scn_foffset)
scn_foffset = scnhdr[i].sh_offset;
break;
case SHT_STRTAB:
if ((strndx < 0) && (i != elfhdr. e_shstrndx))
strndx = i;
if (scnhdr[i].sh_offset < scn_foffset)
scn_foffset = scnhdr[i].sh_offset;
break;
case SHT_RELA:
break;
case SHT_NOBITS:
break;
default:
/* unknown section type */
break;
}
}
/*
* Check for symbol table existence and for string
* table existence AFTER symbol table.
*/
if ((symndx < 0) || (strndx < 0))
{
return FALSE;
}
if (symndx < strndx)
{
/*
* The symbol table entries MUST exist before the string
* entries, or else this information comes too late.
* (Unless you want to do a third pass!?? Not!
*/
return TRUE;
}
else
{
return FALSE;
}
}
void displayProgramHeader(Elf32_Phdr* header)
{
printf(" p_type: %08X\n",header->p_type);
printf(" p_offset: %08X\n",header->p_offset);
printf(" p_vaddr: %08X\n",header->p_vaddr);
printf(" p_paddr: %08X\n",header->p_paddr);
printf(" p_filesz: %08X\n",header->p_filesz);
printf(" p_memsz: %08X\n",header->p_memsz);
printf(" p_flags: %08X\n",header->p_flags);
printf(" p_align: %08X\n",header->p_align);
}
/********************************************************************/
static void
elfReadProgramHeader()
{
Elf32_Phdr pgmhdr;
int i;
char c;
if (elfhdr.e_phnum)
{
/*
* Seek to Program Headers.
*/
for (i = elfBytesRead; i < elfhdr.e_phoff; i++)
elfRead(&c, 1);
for (i = 0; i < elfhdr.e_phnum; ++i)
{
elfRead((char *)&pgmhdr, sizeof(Elf32_Phdr));
// displayProgramHeader(&pgmhdr);
}
}
}
void displayHeader()
{
printf("\ne_type: %08X\n",elfhdr.e_type);
printf("e_machine: %08X\n",elfhdr.e_machine);
printf("e_version: %08X\n",elfhdr.e_version);
printf("e_entry: %08X\n",elfhdr.e_entry);
printf("e_phoff: %08X\n",elfhdr.e_phoff);
printf("e_shoff: %08X\n",elfhdr.e_shoff);
printf("e_flags: %08X\n",elfhdr.e_flags);
printf("e_ehsize: %04X\n",elfhdr.e_ehsize);
printf("e_phentsize: %04X\n",elfhdr.e_phentsize);
printf("e_phnum: %04X\n",elfhdr.e_phnum);
printf("e_shentsize: %04X\n",elfhdr.e_shentsize);
printf("e_shnum: %04X\n",elfhdr.e_shnum);
printf("e_shstrndx: %04X\n",elfhdr.e_shstrndx);
}
int elfValidateHeader()
{
if(elfhdr.e_type != ET_EXEC)
{
printf("\nUnsupported ELF type (non executable)\n");
return 0;
}
if(elfhdr.e_machine != EM_MIPS)
{
printf("\nUnsuported Machine type (non MIPS)\n");
return 0;
}
if(elfhdr.e_version != EV_CURRENT)
{
printf("\nInvalid ELF version\n");
return 0;
}
if (elfhdr.e_ehsize != sizeof(Elf32_Ehdr))
{
printf("\nInvalid File Header Size\n");
return 0;
}
if (elfhdr.e_phentsize != sizeof(Elf32_Phdr))
{
printf("\nInvalid Program Header Size\n");
return 0;
}
if (elfhdr.e_shentsize != sizeof(Elf32_Shdr))
{
printf("\nInvalid Section Header Size\n");
return 0;
}
if (elfhdr.e_shnum > ELF_MAX_HDR)
{
printf("\bError: Too many Section Headers!!!\n");
return 0;
}
// displayHeader();
}
int isElf()
{
return elfhdr.e_ident.EI_MAG[0] == 0x7f &&
elfhdr.e_ident.EI_MAG[1] == 'E' &&
elfhdr.e_ident.EI_MAG[2] == 'L' &&
elfhdr.e_ident.EI_MAG[3] == 'F';
}
int elfReadHeader()
{
elfBytesRead = 0;
return elfRead(&elfhdr, sizeof(Elf32_Ehdr));
}
void* readElf()
{
if(elfValidateHeader())
{
if (elfhdr.e_phoff < elfhdr.e_shoff)
{
elfReadProgramHeader();
if(!elfReadSectionHeader())
return (void*) 0;
}
else
{
if(!elfReadSectionHeader())
return (void*) 0;
elfReadProgramHeader();
}
if (elfBytesRead > scn_foffset)
{
elfClose();
elfOpen(elfFileName); //start at beginning of file
}
if(elfReadSectionData(&elfhdr))
return (void*) elfhdr.e_entry;
}
return 0;
}
/********************************************************************/
void* elfLoadImage(DataFunctions dataFunctions, const char* fileName)
{
void* entryPoint = (void*) 0;
fileAccessFunctions = dataFunctions;
stringCopy(fileName, elfFileName);
showProgress(0); //dont show status dots
if(elfOpen(elfFileName) && elfReadHeader() && isElf())
{
showProgress(1);
printf("\n---------------------------------------------\n");
printf("Loading Image: %12s (Format = ELF)\n", fileName);
if(entryPoint = readElf())
printf("\nImage Loaded Successfully.\n");
else
printf("\nError Loading Image File.\n");
printf("---------------------------------------------\n");
}
elfClose();
return entryPoint;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -