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