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

📄 update.c

📁 freescale的bdm调试工具软件.包括原理图,和cpld源代码.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * update.c - implementation of the elf_update(3) function. * Copyright (C) 1995 - 2006 Michael Riepe *  * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. *  * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. *  * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include <private.h>#ifndef lintstatic const char rcsid[] = "@(#) $Id: update.c,v 1.1 2008/06/16 00:01:22 cjohns Exp $";#endif /* lint */#include <errno.h>#if HAVE_MMAP#include <sys/mman.h>#endif /* HAVE_MMAP */static const unsigned short __encoding = ELFDATA2LSB + (ELFDATA2MSB << 8);#define native_encoding (*(unsigned char*)&__encoding)#define rewrite(var,val,f)	\    do{if((var)!=(val)){(var)=(val);(f)|=ELF_F_DIRTY;}}while(0)#define align(var,val)		\    do{if((val)>1){(var)+=(val)-1;(var)-=(var)%(val);}}while(0)#undef max#define max(a,b)		((a)>(b)?(a):(b))static off_tscn_data_layout(Elf_Scn *scn, unsigned v, unsigned type, size_t *algn, unsigned *flag) {    Elf *elf = scn->s_elf;    Elf_Data *data;    int layout = (elf->e_elf_flags & ELF_F_LAYOUT) == 0;    size_t scn_align = 1;    size_t len = 0;    Scn_Data *sd;    size_t fsize;    if (!(sd = scn->s_data_1)) {	/* no data in section */	*algn = scn_align;	return (off_t)len;    }    /* load data from file, if any */    if (!(data = elf_getdata(scn, NULL))) {	return (off_t)-1;    }    elf_assert(data == &sd->sd_data);    for (; sd; sd = sd->sd_link) {	elf_assert(sd->sd_magic == DATA_MAGIC);	elf_assert(sd->sd_scn == scn);	if (!valid_version(sd->sd_data.d_version)) {	    return (off_t)-1;	}	fsize = sd->sd_data.d_size;	if (fsize && type != SHT_NOBITS && valid_type(sd->sd_data.d_type)) {	    if (elf->e_class == ELFCLASS32) {		fsize = _elf32_xltsize(&sd->sd_data, v, ELFDATA2LSB, 1);	    }#if __LIBELF64	    else if (elf->e_class == ELFCLASS64) {		fsize = _elf64_xltsize(&sd->sd_data, v, ELFDATA2LSB, 1);	    }#endif /* __LIBELF64 */	    else {		elf_assert(valid_class(elf->e_class));		seterr(ERROR_UNIMPLEMENTED);		return (off_t)-1;	    }	    if (fsize == (size_t)-1) {		return (off_t)-1;	    }	}	if (layout) {	    align(len, sd->sd_data.d_align);	    scn_align = max(scn_align, sd->sd_data.d_align);	    rewrite(sd->sd_data.d_off, (off_t)len, sd->sd_data_flags);	    len += fsize;	}	else {	    len = max(len, sd->sd_data.d_off + fsize);	}	*flag |= sd->sd_data_flags;    }    *algn = scn_align;    return (off_t)len;}static size_tscn_entsize(const Elf *elf, unsigned version, unsigned stype) {    Elf_Type type;    switch ((type = _elf_scn_type(stype))) {	case ELF_T_BYTE:	    return 0;	case ELF_T_VDEF:	case ELF_T_VNEED:	    return 0;	/* What else can I do?  Thank you, Sun! */	default:	    return _fsize(elf->e_class, version, type);    }}static off_t_elf32_layout(Elf *elf, unsigned *flag) {    int layout = (elf->e_elf_flags & ELF_F_LAYOUT) == 0;    Elf32_Ehdr *ehdr = (Elf32_Ehdr*)elf->e_ehdr;    size_t off = 0;    unsigned version;    unsigned encoding;    size_t align_addr;    size_t entsize;    unsigned phnum;    unsigned shnum;    Elf_Scn *scn;    *flag = elf->e_elf_flags | elf->e_phdr_flags;    if ((version = ehdr->e_version) == EV_NONE) {	version = EV_CURRENT;    }    if (!valid_version(version)) {	seterr(ERROR_UNKNOWN_VERSION);	return -1;    }    if ((encoding = ehdr->e_ident[EI_DATA]) == ELFDATANONE) {	encoding = native_encoding;    }    if (!valid_encoding(encoding)) {	seterr(ERROR_UNKNOWN_ENCODING);	return -1;    }    entsize = _fsize(ELFCLASS32, version, ELF_T_EHDR);    elf_assert(entsize);    rewrite(ehdr->e_ehsize, entsize, elf->e_ehdr_flags);    off = entsize;    align_addr = _fsize(ELFCLASS32, version, ELF_T_ADDR);    elf_assert(align_addr);    if ((phnum = elf->e_phnum)) {	entsize = _fsize(ELFCLASS32, version, ELF_T_PHDR);	elf_assert(entsize);	if (layout) {	    align(off, align_addr);	    rewrite(ehdr->e_phoff, off, elf->e_ehdr_flags);	    off += phnum * entsize;	}	else {	    off = max(off, ehdr->e_phoff + phnum * entsize);	}    }    else {	entsize = 0;	if (layout) {	    rewrite(ehdr->e_phoff, 0, elf->e_ehdr_flags);	}    }    if (phnum >= PN_XNUM) {	Elf_Scn *scn = elf->e_scn_1;	Elf32_Shdr *shdr = &scn->s_shdr32;	elf_assert(scn);	elf_assert(scn->s_index == 0);	rewrite(shdr->sh_info, phnum, scn->s_shdr_flags);	*flag |= scn->s_shdr_flags;	phnum = PN_XNUM;    }    rewrite(ehdr->e_phnum, phnum, elf->e_ehdr_flags);    rewrite(ehdr->e_phentsize, entsize, elf->e_ehdr_flags);    for (scn = elf->e_scn_1, shnum = 0; scn; scn = scn->s_link, ++shnum) {	Elf32_Shdr *shdr = &scn->s_shdr32;	size_t scn_align = 1;	off_t len;	elf_assert(scn->s_index == shnum);	*flag |= scn->s_scn_flags;	if (scn->s_index == SHN_UNDEF) {	    rewrite(shdr->sh_entsize, 0, scn->s_shdr_flags);	    if (layout) {		rewrite(shdr->sh_offset, 0, scn->s_shdr_flags);		rewrite(shdr->sh_size, 0, scn->s_shdr_flags);		rewrite(shdr->sh_addralign, 0, scn->s_shdr_flags);	    }	    *flag |= scn->s_shdr_flags;	    continue;	}	if (shdr->sh_type == SHT_NULL) {	    *flag |= scn->s_shdr_flags;	    continue;	}	len = scn_data_layout(scn, version, shdr->sh_type, &scn_align, flag);	if (len == -1) {	    return -1;	}	/*	 * Never override the program's choice.	 */	if (shdr->sh_entsize == 0) {	    entsize = scn_entsize(elf, version, shdr->sh_type);	    if (entsize > 1) {		rewrite(shdr->sh_entsize, entsize, scn->s_shdr_flags);	    }	}	if (layout) {	    align(off, scn_align);	    rewrite(shdr->sh_offset, off, scn->s_shdr_flags);	    rewrite(shdr->sh_size, (size_t)len, scn->s_shdr_flags);	    rewrite(shdr->sh_addralign, scn_align, scn->s_shdr_flags);	    if (shdr->sh_type != SHT_NOBITS) {		off += (size_t)len;	    }	}	else if ((size_t)len > shdr->sh_size) {	    seterr(ERROR_SCN2SMALL);	    return -1;	}	else {	    Elf_Scn *scn2;	    size_t end1, end2;	    end1 = shdr->sh_offset;	    if (shdr->sh_type != SHT_NOBITS) {		end1 += shdr->sh_size;	    }	    if (shdr->sh_offset < off) {		/*		 * check for overlapping sections		 */		for (scn2 = elf->e_scn_1; scn2; scn2 = scn2->s_link) {		    if (scn2 == scn) {			break;		    }		    end2 = scn2->s_shdr32.sh_offset;		    if (scn2->s_shdr32.sh_type != SHT_NOBITS) {			end2 += scn2->s_shdr32.sh_size;		    }		    if (end1 > scn2->s_shdr32.sh_offset		     && end2 > shdr->sh_offset) {			seterr(ERROR_SCN_OVERLAP);			return -1;		    }		}	    }	    if (off < end1) {		off = end1;	    }	}	*flag |= scn->s_shdr_flags;    }    if (shnum) {	entsize = _fsize(ELFCLASS32, version, ELF_T_SHDR);	elf_assert(entsize);	if (layout) {	    align(off, align_addr);	    rewrite(ehdr->e_shoff, off, elf->e_ehdr_flags);	    off += shnum * entsize;	}	else {	    off = max(off, ehdr->e_shoff + shnum * entsize);	}    }    else {	entsize = 0;	if (layout) {	    rewrite(ehdr->e_shoff, 0, elf->e_ehdr_flags);	}    }    if (shnum >= SHN_LORESERVE) {	Elf_Scn *scn = elf->e_scn_1;	Elf32_Shdr *shdr = &scn->s_shdr32;	elf_assert(scn->s_index == 0);	rewrite(shdr->sh_size, shnum, scn->s_shdr_flags);	*flag |= scn->s_shdr_flags;	shnum = 0;    }    rewrite(ehdr->e_shnum, shnum, elf->e_ehdr_flags);    rewrite(ehdr->e_shentsize, entsize, elf->e_ehdr_flags);    rewrite(ehdr->e_ident[EI_MAG0], ELFMAG0, elf->e_ehdr_flags);    rewrite(ehdr->e_ident[EI_MAG1], ELFMAG1, elf->e_ehdr_flags);    rewrite(ehdr->e_ident[EI_MAG2], ELFMAG2, elf->e_ehdr_flags);    rewrite(ehdr->e_ident[EI_MAG3], ELFMAG3, elf->e_ehdr_flags);    rewrite(ehdr->e_ident[EI_CLASS], ELFCLASS32, elf->e_ehdr_flags);    rewrite(ehdr->e_ident[EI_DATA], encoding, elf->e_ehdr_flags);    rewrite(ehdr->e_ident[EI_VERSION], version, elf->e_ehdr_flags);    rewrite(ehdr->e_version, version, elf->e_ehdr_flags);    *flag |= elf->e_ehdr_flags;    return off;}#if __LIBELF64static off_t_elf64_layout(Elf *elf, unsigned *flag) {    int layout = (elf->e_elf_flags & ELF_F_LAYOUT) == 0;    Elf64_Ehdr *ehdr = (Elf64_Ehdr*)elf->e_ehdr;    size_t off = 0;    unsigned version;    unsigned encoding;    size_t align_addr;    size_t entsize;    unsigned phnum;    unsigned shnum;    Elf_Scn *scn;    *flag = elf->e_elf_flags | elf->e_phdr_flags;    if ((version = ehdr->e_version) == EV_NONE) {	version = EV_CURRENT;    }    if (!valid_version(version)) {	seterr(ERROR_UNKNOWN_VERSION);	return -1;    }    if ((encoding = ehdr->e_ident[EI_DATA]) == ELFDATANONE) {	encoding = native_encoding;    }    if (!valid_encoding(encoding)) {	seterr(ERROR_UNKNOWN_ENCODING);	return -1;    }    entsize = _fsize(ELFCLASS64, version, ELF_T_EHDR);    elf_assert(entsize);    rewrite(ehdr->e_ehsize, entsize, elf->e_ehdr_flags);    off = entsize;    align_addr = _fsize(ELFCLASS64, version, ELF_T_ADDR);    elf_assert(align_addr);    if ((phnum = elf->e_phnum)) {	entsize = _fsize(ELFCLASS64, version, ELF_T_PHDR);	elf_assert(entsize);	if (layout) {	    align(off, align_addr);	    rewrite(ehdr->e_phoff, off, elf->e_ehdr_flags);	    off += phnum * entsize;	}	else {	    off = max(off, ehdr->e_phoff + phnum * entsize);	}    }    else {	entsize = 0;	if (layout) {	    rewrite(ehdr->e_phoff, 0, elf->e_ehdr_flags);	}    }    if (phnum >= PN_XNUM) {	Elf_Scn *scn = elf->e_scn_1;	Elf32_Shdr *shdr = &scn->s_shdr32;	/* modify first section header, too! */	elf_assert(scn);	elf_assert(scn->s_index == 0);	rewrite(shdr->sh_info, phnum, scn->s_shdr_flags);	*flag |= scn->s_shdr_flags;	phnum = PN_XNUM;    }    rewrite(ehdr->e_phnum, phnum, elf->e_ehdr_flags);    rewrite(ehdr->e_phentsize, entsize, elf->e_ehdr_flags);    for (scn = elf->e_scn_1, shnum = 0; scn; scn = scn->s_link, ++shnum) {	Elf64_Shdr *shdr = &scn->s_shdr64;	size_t scn_align = 1;	off_t len;	elf_assert(scn->s_index == shnum);	*flag |= scn->s_scn_flags;	if (scn->s_index == SHN_UNDEF) {	    rewrite(shdr->sh_entsize, 0, scn->s_shdr_flags);	    if (layout) {		rewrite(shdr->sh_offset, 0, scn->s_shdr_flags);		rewrite(shdr->sh_size, 0, scn->s_shdr_flags);		rewrite(shdr->sh_addralign, 0, scn->s_shdr_flags);	    }	    *flag |= scn->s_shdr_flags;	    continue;	}	if (shdr->sh_type == SHT_NULL) {	    *flag |= scn->s_shdr_flags;	    continue;	}	len = scn_data_layout(scn, version, shdr->sh_type, &scn_align, flag);	if (len == -1) {	    return -1;	}	/*	 * Never override the program's choice.	 */	if (shdr->sh_entsize == 0) {	    entsize = scn_entsize(elf, version, shdr->sh_type);	    if (entsize > 1) {		rewrite(shdr->sh_entsize, entsize, scn->s_shdr_flags);	    }	}	if (layout) {	    align(off, scn_align);	    rewrite(shdr->sh_offset, off, scn->s_shdr_flags);	    rewrite(shdr->sh_size, (size_t)len, scn->s_shdr_flags);	    rewrite(shdr->sh_addralign, scn_align, scn->s_shdr_flags);	    if (shdr->sh_type != SHT_NOBITS) {		off += (size_t)len;	    }	}	else if ((size_t)len > shdr->sh_size) {	    seterr(ERROR_SCN2SMALL);	    return -1;	}	else {	    Elf_Scn *scn2;	    size_t end1, end2;	    end1 = shdr->sh_offset;	    if (shdr->sh_type != SHT_NOBITS) {		end1 += shdr->sh_size;	    }	    if (shdr->sh_offset < off) {		/*		 * check for overlapping sections		 */		for (scn2 = elf->e_scn_1; scn2; scn2 = scn2->s_link) {		    if (scn2 == scn) {			break;		    }		    end2 = scn2->s_shdr64.sh_offset;		    if (scn2->s_shdr64.sh_type != SHT_NOBITS) {			end2 += scn2->s_shdr64.sh_size;		    }		    if (end1 > scn2->s_shdr64.sh_offset		     && end2 > shdr->sh_offset) {			seterr(ERROR_SCN_OVERLAP);			return -1;		    }		}	    }	    if (off < end1) {		off = end1;	    }	}	*flag |= scn->s_shdr_flags;    }    if (shnum) {	entsize = _fsize(ELFCLASS64, version, ELF_T_SHDR);	elf_assert(entsize);	if (layout) {	    align(off, align_addr);	    rewrite(ehdr->e_shoff, off, elf->e_ehdr_flags);	    off += shnum * entsize;	}	else {	    off = max(off, ehdr->e_shoff + shnum * entsize);	}    }    else {	entsize = 0;	if (layout) {	    rewrite(ehdr->e_shoff, 0, elf->e_ehdr_flags);	}    }    if (shnum >= SHN_LORESERVE) {	Elf_Scn *scn = elf->e_scn_1;	Elf64_Shdr *shdr = &scn->s_shdr64;	elf_assert(scn->s_index == 0);	rewrite(shdr->sh_size, shnum, scn->s_shdr_flags);	*flag |= scn->s_shdr_flags;	shnum = 0;    }    rewrite(ehdr->e_shnum, shnum, elf->e_ehdr_flags);    rewrite(ehdr->e_shentsize, entsize, elf->e_ehdr_flags);    rewrite(ehdr->e_ident[EI_MAG0], ELFMAG0, elf->e_ehdr_flags);

⌨️ 快捷键说明

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