⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 elf.c

📁 umon bootloader source code, support mips cpu.
💻 C
📖 第 1 页 / 共 3 页
字号:
/* elf.c:
 * Perform some dumps/displays/conversions on the elf file format.
 *
 * General notice:
 * This code is part of a boot-monitor package developed as a generic base
 * platform for embedded system designs.  As such, it is likely to be
 * distributed to various projects beyond the control of the original
 * author.  Please notify the author of any enhancements made or bugs found
 * so that all may benefit from the changes.  In addition, notification back
 * to the author will allow the new user to pick up changes that may have
 * been made by other users after this version of the code was distributed.
 *
 * Author:	Ed Sutter
 * email:	esutter@lucent.com		(home: lesutter@worldnet.att.net)
 * phone:	908-582-2351			(home: 908-889-5161)
 */
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "elf.h"
#include "utils.h"
#include "../zlib/zlib.h"

#ifndef O_BINARY
#define O_BINARY 0
#endif

#define USE_OFFSET_DELTA	0

void ZipElfSections(int), ElfToBinary(char *);
void StripElfFile(char *,char *), ShowElfMap(int);
void ShowAppend(void), ShowElfHdr(void), ShowSections(int);
Elf32_Half GetElfSectionHdrs(void);
struct elf_fhdr *GetElfFileHdr(struct elf_fhdr *);
char *VerboseShtype(unsigned long); 
char *VerboseShflags(unsigned long), *GetElfSectionName(unsigned long);

struct	elf_fhdr Ehdr;
struct	elf_shdr *ScnTbl;
struct	elf_phdr *PhdrTbl;
char	*elfFname;
unsigned char PadByte;
int 	elfFD, debug, xdebug, Ecvt, verbose, insertPAD;
int		remove_zouts = 1;

/* open verbosity: */
#define SHOWELFHDR		0x0001
#define SHOWSECTIONS	0x0002
#define SHOWMAP			0x0004
#define SHOWMAPOFFSET	0x0008
#define SHOWAPPEND		0x0010
#define SHOWPRGMHDR		0x0020

/* The Linux box that I tried to build this on did not have tell(),
 * so this is a very inefficient equivalent...
 * Originally, I thought lseek(fd,0,SEEK_CUR) would work, but
 * that generates an error on linux due to a bad argument; apparently
 * it doesn't like the value of 0 for the offset when 'whence' is set to
 * SEEK_CUR.
 */
#ifndef BUILD_WITH_VCC
long
tell(int fd)
{
	Lseek(fd,1,SEEK_CUR);
	return(Lseek(fd,-1,SEEK_CUR));
}
#endif

void
ShowAppend(void)
{
	int	i;
	char	c;
	Elf32_Word	maxsize;
	Elf32_Off	maxoff;
	struct	elf_shdr	*eshdr;

	/* Find the highest offset then seek to the end of that section. This */
	/* should be the end of the REAL data in the elf file.  Any remaining */
	/* stuff has been appended (hopefully!). */
	maxoff = 0;
	for(i=0;i<Ehdr.e_shnum;i++) {
		eshdr = &ScnTbl[i];
		if (eshdr->sh_offset > maxoff) {
			maxoff = eshdr->sh_offset;
			maxsize = eshdr->sh_size;
		}
	}
	Lseek(elfFD,maxoff+maxsize,SEEK_SET);
	while(1) {
		if (read(elfFD,&c,1) != 1)
			break;
		putchar(c);
	}
}

void
ShowElfHdr(void)
{
	int	i, j;

	printf("\t\tELF FILE HEADER\n");
	printf("E_IDENT (hex):		");
	for(i=0;i<EI_NIDENT;i++)
		printf("%02x ",Ehdr.e_ident[i]);
	printf("\n");
	printf("File Type:			0x%x\n",Ehdr.e_type);
	printf("Machine:			0x%x\n",Ehdr.e_machine);
	printf("Version:			0x%x\n",Ehdr.e_version);
	printf("Entrypoint:			0x%08x\n",Ehdr.e_entry);
	printf("Program Hdr Tbl Offset:		0x%x\n",Ehdr.e_phoff);
	printf("Section Hdr Tbl Offset:		0x%x\n",Ehdr.e_shoff);
	printf("Processor-specific flags:	0x%08x\n",Ehdr.e_flags);
	printf("ELF Header size:		%u\n",Ehdr.e_ehsize);
	printf("Size of 1 Pgm Hdr Entry:	%u\n",Ehdr.e_phentsize);
	printf("# of entries in Pgm Hdr Tbl:	%u\n",Ehdr.e_phnum);
	printf("Size of 1 Scn Hdr Entry:	%u\n",Ehdr.e_shentsize);
	printf("# of entries in Scn Hdr Tbl:	%u\n",Ehdr.e_shnum);
	printf("ScnHdr string Tbl Index:	0x%x\n",Ehdr.e_shstrndx);
}

void
ShowProgramHdrTbl(int verbose)
{
	int	i, j;

	printf("\t\tProgram Header Table:\n");
	for(i=0;i<Ehdr.e_phnum;i++) {
		printf("PHDR[%d]:\n",i);
		printf("p_type:      0x%lx\n",PhdrTbl[i].p_type);
		printf("p_offset:    0x%lx\n",PhdrTbl[i].p_offset);
		printf("p_vaddr:     0x%lx\n",PhdrTbl[i].p_vaddr);
		printf("p_paddr:     0x%lx\n",PhdrTbl[i].p_paddr);
		printf("p_filesz:    0x%lx\n",PhdrTbl[i].p_filesz);
		printf("p_memsz:     0x%lx\n",PhdrTbl[i].p_memsz);
		printf("p_flags:     0x%lx\n",PhdrTbl[i].p_flags);
		printf("p_align:     0x%lx\n",PhdrTbl[i].p_align);
	}
}

void
ShowSections(int verbose)
{
	int	i;
	unsigned long	size;
	char	buf[32];
	struct	elf_shdr	*eshdr;

	if (debug >= 2)
		fprintf(stderr,"ShowSections()\n");

	for(i=0;i<Ehdr.e_shnum;i++) {
		eshdr = &ScnTbl[i];
		size = eshdr->sh_size;
		if (size)
			size--;
		printf("%10s: 0x%08x..0x%08x (%ld bytes) %s %s\n",
			GetElfSectionName(eshdr->sh_name),
			eshdr->sh_addr,eshdr->sh_addr+size,eshdr->sh_size,
			VerboseShflags(eshdr->sh_flags),
			VerboseShtype(eshdr->sh_type));
		if (verbose) {
			printf("         offset=   0x%08x, link=   0x%08x, info=0x%08x\n",
				eshdr->sh_offset, eshdr->sh_link, eshdr->sh_info);
			printf("         addralign=0x%08x, entsize=0x%08x\n\n",
				eshdr->sh_addralign, eshdr->sh_entsize);
		}
	}
}

/* FindLowestSectionInFile():
 * The section table (ScnTbl[] array) contains a list of all sections in
 * the ELF file.  I had thought that this table listed the sections
 * in the same order as they exist in the file (meaning that the section
 * pointed to by ScnTbl[1] was before the section pointed to by ScnTbl[2]).
 * Turns out that this is not necessarily the case, so this function simply
 * returns the offset to the lowest section in the file.
 */
long
FindLowestSectionInFile(void)
{
	int	i;
	Elf32_Off	lowest_offset;

	lowest_offset = 0xffffffff;
	for(i=1;i<Ehdr.e_shnum;i++) {
		if ((ScnTbl[i].sh_size) &&
			(ScnTbl[i].sh_offset < lowest_offset))
			lowest_offset = ScnTbl[i].sh_offset;
	}
	if (debug >= 1)
		fprintf(stderr,"lowest section in file = 0x%lx\n",lowest_offset);
	return(lowest_offset);
}

/* ZipElfSections():
 * First pass...
 *   Create one file of compressed data for each section to be compressed.
 * Second pass...
 *   Replace each original section with the data from the compressed file
 *   and adjust header information appropriately.
 */
void
ZipElfSections(int zlevel)
{
	uchar	*cp;
	FILE	*zout;
	unsigned long	shoffz, offset_delta;
	int		zipfd, sidx, reduction;
	char	zoutfile[128], zipto[128], mode[16];
	struct	elf_shdr *sptr, *scntbl_z, *sptr_z;
	struct stat zstat;
	Elf32_Off	lowest_section_offset;

	sprintf(mode,"wb%d ",zlevel);
	sprintf(zipto,"%s.ezip",elfFname);
	fprintf(stderr,"Compressing %s into %s \n",elfFname,zipto);

	/* Make a copy of the section table... */
	scntbl_z = (struct elf_shdr *)Malloc(Ehdr.e_shnum * Ehdr.e_shentsize);
	memcpy(scntbl_z,ScnTbl,Ehdr.e_shnum * Ehdr.e_shentsize);

	reduction = 0;

	/* For each section, if it is of the appropriate type, compress it to
	 * a file named "_section_name_%d.zip".
	 */
	for(sptr=ScnTbl,sidx=0;sidx<Ehdr.e_shnum;sidx++,sptr++) {
		char	*name;
			
		name = GetElfSectionName(ScnTbl[sidx].sh_name);

		if ((sptr->sh_flags & SHF_ALLOC) &&
			(sptr->sh_type != SHT_NOBITS) && (sptr->sh_size)) {

			sprintf(zoutfile,"_%s_%d.zip",name,sidx);
			unlink(zoutfile);

			cp = (uchar *)Malloc(sptr->sh_size);
			Lseek(elfFD,sptr->sh_offset,SEEK_SET);
			read(elfFD,cp,sptr->sh_size);

	    	zout = gzopen(zoutfile, mode);
		    if (zout == NULL) {
		        fprintf(stderr, "can't gzopen %s\n", zoutfile);
		        exit(1);
		    }
	        if (gzwrite(zout, cp, (unsigned)sptr->sh_size) != sptr->sh_size) {
		        fprintf(stderr, "gzwrite failed\n");
				exit(1);
			}
		    if (gzclose(zout) != Z_OK) {
		        fprintf(stderr, "gzclose failed\n");
				exit(1);
			}
	
			free(cp);
			
			stat(zoutfile,&zstat);
			printf("Sec %-8s compressed from %8d to %8d bytes.\n",
				name,sptr->sh_size,zstat.st_size);
			reduction += (sptr->sh_size - zstat.st_size);
		}
		free(name);
	}
	printf("Total reduction: %d bytes\n",reduction);

	/* Create the destination file... */
	unlink(zipto);
	if ((zipfd = open(zipto,O_WRONLY|O_BINARY|O_CREAT,0777))==-1)
	{
		perror(zipto);
		exit(1);
	}

	/* Do a blind copy of all data up to the start of the first
	 * section.  Note that it is not required that the sections be
	 * listed in ScnTbl[] in the same order as they are arranged within
	 * the file, so we must determine which section in the table is first
	 * in the file.  Use the lowest_section_offset variable as a pointer
	 * to the first location in the new file into which the compressed
	 * sections can be placed.
	 *
	 * Fix...
	 * Turns out that the "blind copy" approach wastes memory in certain
	 * cases... For some reason some elf files have an empty 64K
	 * block of space between the end of the program header table and the
	 * first section, so this meant that a 64k block of space was wasted.
	 * 
	 * In the first fix for the above problem, the lowest_section_offset 
	 * pointed to the address just after the end of the file header (below
	 * the wasted 64k block).  This was incorrect because it chopped off
	 * the program header; hence, now the lowest_sectino_offset points to
	 * the address just after the program header...
	 */
#if 0	/* first version... */
	if (verbose)
		fprintf(stderr,"Copying first %ld bytes\n",ScnTbl[1].sh_offset);
	Lseek(elfFD,0,SEEK_SET);
	lowest_section_offset = FindLowestSectionInFile();
	cp = Malloc(lowest_section_offset);
	Read(elfFD,cp,lowest_section_offset);
	Write(zipfd,cp,lowest_section_offset);
	free(cp);
#else
	if (verbose)
		fprintf(stderr,"Copying ELF file & program hdr\n");

	Lseek(elfFD,0,SEEK_SET);
	lowest_section_offset = Ehdr.e_phoff+(Ehdr.e_phentsize*Ehdr.e_phnum);
	cp = Malloc(lowest_section_offset);
	Read(elfFD,cp,lowest_section_offset);
	Write(zipfd,cp,lowest_section_offset);
	free(cp);
#endif

	offset_delta = 0;

	/* For each section, copy from original file or from zipped file to */
	/* the new file... */
	for(sptr=&ScnTbl[1],sidx=1;sidx<Ehdr.e_shnum;sidx++,sptr++) {
		char	*name;
			
		sptr_z = scntbl_z+sidx;

		name = GetElfSectionName(ScnTbl[sidx].sh_name);
		if ((sptr->sh_flags & SHF_ALLOC) &&
			(sptr->sh_type != SHT_NOBITS) && (sptr->sh_size)) {
			int secfd;

			sprintf(zoutfile,"_%s_%d.zip",name,sidx);
			stat(zoutfile,&zstat);
			if (verbose)
				fprintf(stderr,"Replacing sec %s with %s (%d bytes)\n",
					name,zoutfile,zstat.st_size);
			sptr_z->sh_size = zstat.st_size;
#if USE_OFFSET_DELTA
			sptr_z->sh_offset -= offset_delta;
#else
			sptr_z->sh_offset = tell(zipfd);
#endif
			if(debug) {
				fprintf(stderr,"offset_delta += %d (%d-%d)\n",
				(sptr->sh_size - sptr_z->sh_size),sptr->sh_size,
				sptr_z->sh_size);
			}
			offset_delta += (sptr->sh_size - sptr_z->sh_size);
			if ((secfd = open(zoutfile,O_RDONLY|O_BINARY)) == -1) {
				fprintf(stderr,"Couldn't open %s\n",zoutfile);
				exit(1);
			}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -