libelf_ehdr.c revision 164190
1139823Simp/*- 2157067Srwatson * Copyright (c) 2006 Joseph Koshy 3157067Srwatson * All rights reserved. 411819Sjulian * 5157067Srwatson * Redistribution and use in source and binary forms, with or without 6157067Srwatson * modification, are permitted provided that the following conditions 711819Sjulian * are met: 811819Sjulian * 1. Redistributions of source code must retain the above copyright 911819Sjulian * notice, this list of conditions and the following disclaimer. 1011819Sjulian * 2. Redistributions in binary form must reproduce the above copyright 1111819Sjulian * notice, this list of conditions and the following disclaimer in the 1211819Sjulian * documentation and/or other materials provided with the distribution. 1311819Sjulian * 1411819Sjulian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1511819Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1611819Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1711819Sjulian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1811819Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1911819Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2011819Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2111819Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2211819Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2311819Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2411819Sjulian * SUCH DAMAGE. 2511819Sjulian * 2611819Sjulian * $FreeBSD: head/lib/libelf/libelf_ehdr.c 164190 2006-11-11 17:16:35Z jkoshy $ 2711819Sjulian */ 2811819Sjulian 2911819Sjulian#include <sys/cdefs.h> 3011819Sjulian__FBSDID("$FreeBSD: head/lib/libelf/libelf_ehdr.c 164190 2006-11-11 17:16:35Z jkoshy $"); 3111819Sjulian 3211819Sjulian#include <assert.h> 3311819Sjulian#include <gelf.h> 3411819Sjulian#include <libelf.h> 3511819Sjulian#include <stdlib.h> 3612057Sjulian 3711819Sjulian#include "_libelf.h" 3811819Sjulian 39116189Sobrien#define EHDR_INIT(E,SZ) do { \ 40116189Sobrien Elf##SZ##_Ehdr *eh = (E); \ 41116189Sobrien eh->e_ident[EI_MAG0] = ELFMAG0; \ 4211819Sjulian eh->e_ident[EI_MAG1] = ELFMAG1; \ 4376166Smarkm eh->e_ident[EI_MAG2] = ELFMAG2; \ 4429024Sbde eh->e_ident[EI_MAG3] = ELFMAG3; \ 4511819Sjulian eh->e_ident[EI_CLASS] = ELFCLASS##SZ; \ 4676166Smarkm eh->e_ident[EI_DATA] = ELFDATANONE; \ 4725345Sjhay eh->e_ident[EI_VERSION] = LIBELF_PRIVATE(version); \ 4811819Sjulian eh->e_machine = EM_NONE; \ 4995759Stanimura eh->e_type = ELF_K_NONE; \ 5011819Sjulian eh->e_version = LIBELF_PRIVATE(version); \ 5111819Sjulian } while (0) 5295759Stanimura 5395759Stanimuravoid * 5411819Sjulian_libelf_ehdr(Elf *e, int ec, int allocate) 5511819Sjulian{ 5611819Sjulian size_t fsz, msz; 5711819Sjulian void *ehdr; 5811819Sjulian void (*xlator)(char *_d, char *_s, size_t _c, int _swap); 5911819Sjulian 6011819Sjulian assert(ec == ELFCLASS32 || ec == ELFCLASS64); 6111819Sjulian 6295759Stanimura if (e == NULL || e->e_kind != ELF_K_ELF) { 6311819Sjulian LIBELF_SET_ERROR(ARGUMENT, 0); 6411819Sjulian return (NULL); 6511819Sjulian } 6611819Sjulian 6711819Sjulian if (e->e_class != ELFCLASSNONE && e->e_class != ec) { 6811819Sjulian LIBELF_SET_ERROR(CLASS, 0); 6933181Seivind return (NULL); 7033181Seivind } 7133181Seivind 7233181Seivind if (e->e_version != EV_CURRENT) { 7333181Seivind LIBELF_SET_ERROR(VERSION, 0); 7433181Seivind return (NULL); 75157068Srwatson } 7611819Sjulian 7725652Sjhay if (e->e_class == ELFCLASSNONE) 78139584Srwatson e->e_class = ec; 7925652Sjhay 80139584Srwatson if (ec == ELFCLASS32) 8111819Sjulian ehdr = (void *) e->e_u.e_elf.e_ehdr.e_ehdr32; 82132045Srwatson else 8325652Sjhay ehdr = (void *) e->e_u.e_elf.e_ehdr.e_ehdr64; 8411819Sjulian 85139931Srwatson if (ehdr != NULL) /* already have a translated ehdr */ 86139931Srwatson return (ehdr); 87139931Srwatson 8825652Sjhay fsz = gelf_fsize(e, ELF_T_EHDR, (size_t) 1, e->e_version); 8925652Sjhay 9025652Sjhay assert(fsz > 0); 9125652Sjhay 9225652Sjhay if (e->e_cmd != ELF_C_WRITE && e->e_rawsize < fsz) { 93139931Srwatson LIBELF_SET_ERROR(HEADER, 0); 9425652Sjhay return (NULL); 9524659Sjhay } 9628270Swollman 9783366Sjulian msz = _libelf_msize(ELF_T_EHDR, ec, EV_CURRENT); 9883366Sjulian 9928270Swollman assert(msz > 0); 10083366Sjulian 10124659Sjhay if ((ehdr = calloc((size_t) 1, msz)) == NULL) { 10224659Sjhay LIBELF_SET_ERROR(RESOURCE, 0); 103151888Srwatson return (NULL); 10424659Sjhay } 10524659Sjhay 10624659Sjhay if (ec == ELFCLASS32) { 107139584Srwatson e->e_u.e_elf.e_ehdr.e_ehdr32 = ehdr; 10883366Sjulian EHDR_INIT(ehdr,32); 10924659Sjhay } else { 11083366Sjulian e->e_u.e_elf.e_ehdr.e_ehdr64 = ehdr; 11124659Sjhay EHDR_INIT(ehdr,64); 11224659Sjhay } 113137386Sphk 114137386Sphk if (allocate) 115137386Sphk e->e_flags |= ELF_F_DIRTY; 116137386Sphk 117137386Sphk if (e->e_cmd == ELF_C_WRITE) 118137386Sphk return (ehdr); 119137386Sphk 120137386Sphk xlator = _libelf_get_translator(ELF_T_EHDR, ELF_TOMEMORY, ec); 121137386Sphk (*xlator)(ehdr, e->e_rawfile, (size_t) 1, 122137386Sphk e->e_byteorder != LIBELF_PRIVATE(byteorder)); 123137386Sphk 124137386Sphk return (ehdr); 125137386Sphk} 126137386Sphk