?? elf.c
字號:
/*
* File: elf.c
* Purpose: Data definitions and routines for downloading ELF files.
*
* Notes:
*
*/
#include "src/include/dbug.h"
#include "src/uif/uif.h"
/********************************************************************/
typedef uint32 Elf32_Addr;
typedef uint32 Elf32_Word;
typedef uint16 Elf32_Half;
typedef uint32 Elf32_Off;
typedef int32 Elf32_Sword;
#define EI_NIDENT 16
#define ELF_IDENT (0x7F454C46) /* _ELF */
#define ELF_ETYPE_RELO (1)
#define ELF_ETYPE_EXEC (2)
#define ELF_EMACHINE_68K (6)
#define ELF_EMACHINE_PPC (20)
#define ELF_EVERSION (1)
typedef struct
{
unsigned char e_ident[EI_NIDENT];
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;
#define SHT_NULL (0)
#define SHT_PROGBITS (1)
#define SHT_SYMTAB (2)
#define SHT_STRTAB (3)
#define SHT_RELA (4)
#define SHT_NOBITS (8)
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;
#define STB_LOCAL (0)
#define STB_GLOBAL (1)
#define STB_WEAK (2)
#define STT_NOTYPE (0)
#define STT_OBJECT (1)
#define STT_FUNC (2)
#define STT_SECTION (3)
#define STT_FILE (4)
#define SHN_UNDEF (0)
#define SHN_ABS (0xfff1)
#define SHN_COMMON (0xfff2)
/********************************************************************/
#ifndef ELF_MAX_HDR
#define ELF_MAX_HDR (20)
#endif
static volatile int elf_bytes_read;
static int symndx, strndx;
static Elf32_Ehdr elfhdr;
static Elf32_Shdr scnhdr[ELF_MAX_HDR];
static uint32 scn_foffset;
/********************************************************************/
static void
elf_read (char *buf, int size)
{
int i;
for (i = 0; i < size; i++)
{
buf[i] = (char)board_dlio_getchar();
++elf_bytes_read;
}
}
/********************************************************************/
static void
elf_read_scndata (Elf32_Ehdr *elfhdr)
{
Elf32_Shdr *scn;
Elf32_Sym syment;
char c, *p;
int i, j, offset, symloaded = FALSE;
uint32 foffset;
char buffer[100];
while (TRUE)
{
/*
* Locate next sequential section using sh_offset
*/
foffset = (uint32)~0;
scn = NULL;
for (i = 0; i < elfhdr->e_shnum; ++i)
{
if (scnhdr[i].sh_offset != 0)
{
if (scnhdr[i].sh_offset < foffset)
{
scn = &scnhdr[i];
foffset = scn->sh_offset;
#ifdef HOST_DEBUG
printf("ScnData: %d\n", i);
#endif
}
}
}
if ((foffset == (uint32)~0) || (scn == NULL))
{
do
{
elf_read(&c, 1);
} while (c != (char)-1);
break; /* done! no more sections */
}
/*
* Seek to Section data.
*/
for (i = elf_bytes_read; i < foffset; i++)
elf_read(&c, 1);
switch (scn->sh_type)
{
case SHT_NULL:
break;
case SHT_PROGBITS:
p = (char *)scn->sh_addr;
if (board_dlio_vda((ADDRESS)p) && scn->sh_size)
{
for (j = 0; j < scn->sh_size; ++j)
{
elf_read((char *)&c, 1);
#ifndef HOST_DEBUG
*p++ = c;
#else
;
#endif
}
}
#if 0
else
{
printf("\bError: Invalid download address: %#08X\n", p);
}
#endif
break;
case SHT_SYMTAB:
while (elf_bytes_read < (scn->sh_offset + scn->sh_size))
{
elf_read((char *)&syment, sizeof(Elf32_Sym));
#ifdef HOST_DEBUG
printf(" st_name: %08X\n",syment.st_name);
printf(" st_value: %08X\n",syment.st_value);
printf(" st_size: %08X\n",syment.st_size);
printf(" st_info: %08X\n",syment.st_info);
printf(" st_other: %08X\n",syment.st_other);
printf(" st_shndx: %08X\n",syment.st_shndx);
#endif
if (((syment.st_info >> 4) == STB_GLOBAL) &&
(((syment.st_info & 15) == STT_OBJECT) ||
((syment.st_info & 15) == STT_NOTYPE) ||
((syment.st_info & 15) == STT_FUNC)))
{
symtab_add_incomplete(syment.st_name,syment.st_value);
}
}
symloaded = TRUE;
break;
case SHT_STRTAB:
if (symloaded)
{
while (elf_bytes_read < (scn->sh_offset + scn->sh_size))
{
p = &buffer[0];
i = 0;
offset = elf_bytes_read - scn->sh_offset;
/* All strings in section are NULL terminated */
c = 'X'; /* non-NULL */
while (c != '\0')
{
elf_read(&c, 1);
if (++i < 100)
{
*p++ = c;
}
else
{
*p = '\0';
}
}
symtab_add_complete(buffer,offset);
#ifdef HOST_DEBUG
printf("String %08X %s\n",offset,buffer);
#endif
}
}
break;
case SHT_RELA:
break;
case SHT_NOBITS:
#if 1
p = (char *)scn->sh_addr;
if (board_dlio_vda((ADDRESS)p))
{
for (j = 0; j < scn->sh_size; ++j)
#ifndef HOST_DEBUG
*p++ = 0;
#else
;
#endif
}
#if 0
else
{
printf("\bError: Invalid download address: %#08X\n", p);
}
#endif
#endif
break;
default:
/* unknown section type */
break;
}
scn->sh_offset = 0; /* marked section as used */
}
}
/********************************************************************/
static int
elf_read_scnhdr (Elf32_Ehdr *elfhdr)
{
int i;
char c;
scn_foffset = (uint32)~0;
symndx = -1;
strndx = -1;
if (elfhdr->e_shnum)
{
/*
* Seek to Section Headers.
*/
for (i = elf_bytes_read; i < elfhdr->e_shoff; i++)
elf_read(&c, 1);
}
else
return FALSE;
#ifdef HOST_DEBUG
printf("elf_bytes_read: %08X %d\n", elf_bytes_read, elf_bytes_read);
#endif
printf("\bSection Headers:\n");
for (i = 0; i < elfhdr->e_shnum; ++i)
{
elf_read((char *)&scnhdr[i], sizeof(Elf32_Shdr));
printf(" Section %d (Type: %08X, Addr: %08X, Size: %08X)\n",
i, scnhdr[i].sh_type, scnhdr[i].sh_addr, scnhdr[i].sh_size);
#ifdef HOST_DEBUG
printf(" sh_name: %08X\n",scnhdr[i].sh_name);
printf(" sh_type: %08X\n",scnhdr[i].sh_type);
printf(" sh_flags: %08X\n",scnhdr[i].sh_flags);
printf(" sh_addr: %08X\n",scnhdr[i].sh_addr);
printf(" sh_offset: %08X\n",scnhdr[i].sh_offset);
printf(" sh_size: %08X\n",scnhdr[i].sh_size);
printf(" sh_link: %08X\n",scnhdr[i].sh_link);
printf(" sh_info: %08X\n",scnhdr[i].sh_info);
printf(" sh_addalgn: %08X\n",scnhdr[i].sh_addralign);
printf(" sh_entsize: %08X\n",scnhdr[i].sh_entsize);
#endif
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:
default:
/* unknown section type */
break;
}
}
#ifdef HOST_DEBUG
printf("elf_bytes_read: %08X %d\n", elf_bytes_read, elf_bytes_read);
#endif
/*
* 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;
}
}
/********************************************************************/
static void
elf_read_pgmhdr(Elf32_Ehdr *elfhdr)
{
Elf32_Phdr pgmhdr;
int i;
char c;
if (elfhdr->e_phnum)
{
/*
* Seek to Program Headers.
*/
for (i = elf_bytes_read; i < elfhdr->e_phoff; i++)
elf_read(&c, 1);
#ifdef HOST_DEBUG
printf("elf_bytes_read: %08X %d\n", elf_bytes_read, elf_bytes_read);
#endif
printf("\bProgram Headers:\n");
for (i = 0; i < elfhdr->e_phnum; ++i)
{
elf_read((char *)&pgmhdr, sizeof(Elf32_Phdr));
printf(" Segment #%d (Vaddr: %08X, Paddr: %08X, Size: %08X)\n",
i, pgmhdr.p_vaddr, pgmhdr.p_paddr, pgmhdr.p_memsz);
#ifdef HOST_DEBUG
printf(" p_type: %08X\n",pgmhdr.p_type);
printf(" p_offset: %08X\n",pgmhdr.p_offset);
printf(" p_vaddr: %08X\n",pgmhdr.p_vaddr);
printf(" p_paddr: %08X\n",pgmhdr.p_paddr);
printf(" p_filesz: %08X\n",pgmhdr.p_filesz);
printf(" p_memsz: %08X\n",pgmhdr.p_memsz);
printf(" p_flags: %08X\n",pgmhdr.p_flags);
printf(" p_align: %08X\n",pgmhdr.p_align);
#endif
}
}
}
/********************************************************************/
static int
elf_read_filehdr (Elf32_Ehdr *elfhdr)
{
/*
* Copy ELF file header
*/
elf_read((char *)elfhdr, sizeof(Elf32_Ehdr));
#ifdef HOST_DEBUG
{
int i;
for (i = 0; i < EI_NIDENT; ++i)
{
printf("%02X ",elfhdr->e_ident[i]);
}
printf("\n");
printf("e_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);
}
#endif
/*
* Check for basic problems
*/
if (elfhdr->e_ident[0] != 0x7F)
goto error;
if (elfhdr->e_ident[1] != 'E')
goto error;
if (elfhdr->e_ident[2] != 'L')
goto error;
if (elfhdr->e_ident[3] != 'F')
goto error;
if (!(elfhdr->e_type & ELF_ETYPE_EXEC))
goto error;
#if 0
#if (defined(CPU_ARCH_CF))
if (elfhdr->e_machine != ELF_EMACHINE_68K)
goto error;
#elif (defined(CPU_ARCH_PPC))
if (elfhdr->e_machine != ELF_EMACHINE_PPC)
goto error;
#else
#error "Unsupported machine"
#endif
#endif
if (elfhdr->e_ehsize != sizeof(Elf32_Ehdr))
goto error;
if (elfhdr->e_phentsize != sizeof(Elf32_Phdr))
goto error;
if (elfhdr->e_shentsize != sizeof(Elf32_Shdr))
goto error;
if (elfhdr->e_shnum > ELF_MAX_HDR)
{
printf("\bError: Too many Section Headers!!!\n");
goto error;
}
/*noerror:*/
cpu_pc_modify(elfhdr->e_entry);
return TRUE;
error:
printf("\bError: Not a recognized ELF file!\n");
return FALSE;
}
/********************************************************************/
int
download_elf (int passno)
{
elf_bytes_read = 0;
/*
* Pass # 1: Obtain headers.
*/
if (passno == 1)
{
/*
* Step 1) Obtain the ELF file header.
*/
if (elf_read_filehdr(&elfhdr) != TRUE)
return -1;
/*
* Step 2) Obtain the Program and Section Headers.
*/
if (elfhdr.e_phoff < elfhdr.e_shoff)
{
elf_read_pgmhdr(&elfhdr);
elf_read_scnhdr(&elfhdr);
}
else
{
elf_read_scnhdr(&elfhdr);
elf_read_pgmhdr(&elfhdr);
}
/*
* The section data follows all headers in the ELF file
*/
if (elf_bytes_read <= scn_foffset)
{
elf_read_scndata(&elfhdr);
return FALSE;
}
return TRUE;
}
else
{
/*
* Pass #2 - Get data
*/
elf_read_scndata(&elfhdr);
return TRUE;
}
}
#ifdef HOST_DEBUG
/********************************************************************/
int
main (int argc, char **argv)
{
int passno;
if (argc != 2)
{
printf("specify filename!\n");
return -1;
}
for (passno = 1; passno <= 2; ++passno)
{
if ((fp = open(argv[1],O_RDONLY)) < 0)
{
printf("Error opening file: %s\n", argv[1]);
return -1;
}
if (download_elf(passno) != TRUE)
{
close(fp);
return;
}
close(fp);
}
return 0;
}
/********************************************************************/
#endif
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -