Keep shadow copies of the e_shnum',
e_phnum' and `e_shstrndx'
members of the ELF Executable Header inside the library-private `struct _Elf' descriptor and only update the underlying Elf{32,64}_Ehdr structure on an elf_update(3) call. These fields of the Ehdr structure are technically `out of bounds' for an application program per the ELF(3) API, but we've seen applications that initialize a new Ehdr structure using memcpy(), messing up the library's invariants. [1] Implement elf_getphnum() and handle ELF objects with more than 64K program header table entries. Reported by: jb [1]
This commit is contained in:
parent
a2dc08f2b8
commit
f6c0f35e07
@ -18,6 +18,7 @@ SRCS= elf_begin.c \
|
|||||||
elf_next.c \
|
elf_next.c \
|
||||||
elf_rand.c \
|
elf_rand.c \
|
||||||
elf_rawfile.c \
|
elf_rawfile.c \
|
||||||
|
elf_phnum.c \
|
||||||
elf_shnum.c \
|
elf_shnum.c \
|
||||||
elf_shstrndx.c \
|
elf_shstrndx.c \
|
||||||
elf_scn.c \
|
elf_scn.c \
|
||||||
@ -46,6 +47,7 @@ SRCS= elf_begin.c \
|
|||||||
libelf_checksum.c \
|
libelf_checksum.c \
|
||||||
libelf_data.c \
|
libelf_data.c \
|
||||||
libelf_ehdr.c \
|
libelf_ehdr.c \
|
||||||
|
libelf_extended.c \
|
||||||
libelf_phdr.c \
|
libelf_phdr.c \
|
||||||
libelf_shdr.c \
|
libelf_shdr.c \
|
||||||
libelf_xlate.c \
|
libelf_xlate.c \
|
||||||
@ -72,6 +74,7 @@ MAN= elf.3 \
|
|||||||
elf_getdata.3 \
|
elf_getdata.3 \
|
||||||
elf_getident.3 \
|
elf_getident.3 \
|
||||||
elf_getscn.3 \
|
elf_getscn.3 \
|
||||||
|
elf_getphnum.3 \
|
||||||
elf_getshnum.3 \
|
elf_getshnum.3 \
|
||||||
elf_getshstrndx.3 \
|
elf_getshstrndx.3 \
|
||||||
elf_hash.3 \
|
elf_hash.3 \
|
||||||
|
@ -39,6 +39,7 @@ global:
|
|||||||
elf_getdata;
|
elf_getdata;
|
||||||
elf_getident;
|
elf_getident;
|
||||||
elf_getscn;
|
elf_getscn;
|
||||||
|
elf_getphnum;
|
||||||
elf_getshnum;
|
elf_getshnum;
|
||||||
elf_getshstrndx;
|
elf_getshstrndx;
|
||||||
elf_hash;
|
elf_hash;
|
||||||
|
@ -71,6 +71,7 @@ extern struct _libelf_globals _libelf;
|
|||||||
*/
|
*/
|
||||||
#define LIBELF_F_MALLOCED 0x010000 /* whether data was malloc'ed */
|
#define LIBELF_F_MALLOCED 0x010000 /* whether data was malloc'ed */
|
||||||
#define LIBELF_F_MMAP 0x020000 /* whether e_rawfile was mmap'ed */
|
#define LIBELF_F_MMAP 0x020000 /* whether e_rawfile was mmap'ed */
|
||||||
|
#define LIBELF_F_SHDRS_LOADED 0x040000 /* whether all shdrs were read in */
|
||||||
|
|
||||||
struct _Elf {
|
struct _Elf {
|
||||||
int e_activations; /* activation count */
|
int e_activations; /* activation count */
|
||||||
@ -107,6 +108,9 @@ struct _Elf {
|
|||||||
Elf64_Phdr *e_phdr64;
|
Elf64_Phdr *e_phdr64;
|
||||||
} e_phdr;
|
} e_phdr;
|
||||||
STAILQ_HEAD(, _Elf_Scn) e_scn; /* section list */
|
STAILQ_HEAD(, _Elf_Scn) e_scn; /* section list */
|
||||||
|
size_t e_nphdr; /* number of Phdr entries */
|
||||||
|
size_t e_nscn; /* number of sections */
|
||||||
|
size_t e_strndx; /* string table section index */
|
||||||
} e_elf;
|
} e_elf;
|
||||||
} e_u;
|
} e_u;
|
||||||
};
|
};
|
||||||
@ -171,9 +175,6 @@ void (*_libelf_get_translator(Elf_Type _t, int _direction, int _elfclass))
|
|||||||
(char *_dst, char *_src, size_t _cnt, int _byteswap);
|
(char *_dst, char *_src, size_t _cnt, int _byteswap);
|
||||||
void *_libelf_getphdr(Elf *_e, int _elfclass);
|
void *_libelf_getphdr(Elf *_e, int _elfclass);
|
||||||
void *_libelf_getshdr(Elf_Scn *_scn, int _elfclass);
|
void *_libelf_getshdr(Elf_Scn *_scn, int _elfclass);
|
||||||
int _libelf_getshnum(Elf *_e, void *_eh, int _elfclass, size_t *_shnum);
|
|
||||||
int _libelf_getshstrndx(Elf *_e, void *_eh, int _elfclass,
|
|
||||||
size_t *_shstrndx);
|
|
||||||
void _libelf_init_elf(Elf *_e, Elf_Kind _kind);
|
void _libelf_init_elf(Elf *_e, Elf_Kind _kind);
|
||||||
int _libelf_malign(Elf_Type _t, int _elfclass);
|
int _libelf_malign(Elf_Type _t, int _elfclass);
|
||||||
size_t _libelf_msize(Elf_Type _t, int _elfclass, unsigned int _version);
|
size_t _libelf_msize(Elf_Type _t, int _elfclass, unsigned int _version);
|
||||||
@ -181,6 +182,7 @@ void *_libelf_newphdr(Elf *_e, int _elfclass, size_t _count);
|
|||||||
Elf_Data *_libelf_release_data(Elf_Data *_d);
|
Elf_Data *_libelf_release_data(Elf_Data *_d);
|
||||||
Elf *_libelf_release_elf(Elf *_e);
|
Elf *_libelf_release_elf(Elf *_e);
|
||||||
Elf_Scn *_libelf_release_scn(Elf_Scn *_s);
|
Elf_Scn *_libelf_release_scn(Elf_Scn *_s);
|
||||||
|
int _libelf_setphnum(Elf *_e, void *_eh, int _elfclass, size_t _phnum);
|
||||||
int _libelf_setshnum(Elf *_e, void *_eh, int _elfclass, size_t _shnum);
|
int _libelf_setshnum(Elf *_e, void *_eh, int _elfclass, size_t _shnum);
|
||||||
int _libelf_setshstrndx(Elf *_e, void *_eh, int _elfclass,
|
int _libelf_setshstrndx(Elf *_e, void *_eh, int _elfclass,
|
||||||
size_t _shstrndx);
|
size_t _shstrndx);
|
||||||
|
87
lib/libelf/elf_getphnum.3
Normal file
87
lib/libelf/elf_getphnum.3
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
.\" Copyright (c) 2006 Joseph Koshy. All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\"
|
||||||
|
.\" This software is provided by Joseph Koshy ``as is'' and
|
||||||
|
.\" any express or implied warranties, including, but not limited to, the
|
||||||
|
.\" implied warranties of merchantability and fitness for a particular purpose
|
||||||
|
.\" are disclaimed. in no event shall Joseph Koshy be liable
|
||||||
|
.\" for any direct, indirect, incidental, special, exemplary, or consequential
|
||||||
|
.\" damages (including, but not limited to, procurement of substitute goods
|
||||||
|
.\" or services; loss of use, data, or profits; or business interruption)
|
||||||
|
.\" however caused and on any theory of liability, whether in contract, strict
|
||||||
|
.\" liability, or tort (including negligence or otherwise) arising in any way
|
||||||
|
.\" out of the use of this software, even if advised of the possibility of
|
||||||
|
.\" such damage.
|
||||||
|
.\"
|
||||||
|
.\" $FreeBSD$
|
||||||
|
.\"
|
||||||
|
.Dd December 16, 2006
|
||||||
|
.Os
|
||||||
|
.Dt ELF_GETPHNUM 3
|
||||||
|
.Sh NAME
|
||||||
|
.Nm elf_getphnum
|
||||||
|
.Nd return the number of program headers in an ELF file
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libelf
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In libelf.h
|
||||||
|
.Ft int
|
||||||
|
.Fn elf_getphnum "Elf *elf" "size_t *phnum"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
Function
|
||||||
|
.Fn elf_getphnum
|
||||||
|
retrieves the number of ELF program headers associated with descriptor
|
||||||
|
.Ar elf
|
||||||
|
and stores it into the location pointed to by argument
|
||||||
|
.Ar phnum .
|
||||||
|
.Pp
|
||||||
|
This routine allows applications to uniformly process both normal ELF
|
||||||
|
objects and ELF objects that use extended numbering.
|
||||||
|
.Pp
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
Function
|
||||||
|
.Fn elf_getphnum
|
||||||
|
returns a non-zero value if successful, or zero in case of an
|
||||||
|
error.
|
||||||
|
.Sh ERRORS
|
||||||
|
Function
|
||||||
|
.Fn elf_getphnum
|
||||||
|
can fail with the following errors:
|
||||||
|
.Bl -tag -width "[ELF_E_RESOURCE]"
|
||||||
|
.It Bq Er ELF_E_ARGUMENT
|
||||||
|
A NULL value was passed in for argument
|
||||||
|
.Ar elf .
|
||||||
|
.It Bq Er ELF_E_ARGUMENT
|
||||||
|
Argument
|
||||||
|
.Ar elf
|
||||||
|
was not for an ELF file.
|
||||||
|
.It Bq Er ELF_E_ARGUMENT
|
||||||
|
Argument
|
||||||
|
.Ar elf
|
||||||
|
lacks an ELF Executable Header.
|
||||||
|
.It Bq Er ELF_E_HEADER
|
||||||
|
The ELF Executable Header associated with argument
|
||||||
|
.Ar elf
|
||||||
|
was corrupt.
|
||||||
|
.It Bq Er ELF_E_SECTION
|
||||||
|
The section header at index
|
||||||
|
.Dv SHN_UNDEF
|
||||||
|
was corrupt.
|
||||||
|
.El
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr elf 3 ,
|
||||||
|
.Xr elf32_getehdr 3 ,
|
||||||
|
.Xr elf64_getehdr 3 ,
|
||||||
|
.Xr elf_getident 3 ,
|
||||||
|
.Xr elf_getshnum 3 ,
|
||||||
|
.Xr elf_getshstrndx 3 ,
|
||||||
|
.Xr gelf 3 ,
|
||||||
|
.Xr gelf_getehdr 3
|
53
lib/libelf/elf_phnum.c
Normal file
53
lib/libelf/elf_phnum.c
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2006 Joseph Koshy
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include <ar.h>
|
||||||
|
#include <libelf.h>
|
||||||
|
|
||||||
|
#include "_libelf.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
elf_getphnum(Elf *e, size_t *phnum)
|
||||||
|
{
|
||||||
|
void *eh;
|
||||||
|
int ec;
|
||||||
|
|
||||||
|
if (e == NULL || e->e_kind != ELF_K_ELF ||
|
||||||
|
((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
|
||||||
|
LIBELF_SET_ERROR(ARGUMENT, 0);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((eh = _libelf_ehdr(e, ec, 0)) == NULL)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
*phnum = e->e_u.e_elf.e_nphdr;
|
||||||
|
|
||||||
|
return (1);
|
||||||
|
}
|
@ -44,7 +44,6 @@ _libelf_load_scn(Elf *e, void *ehdr)
|
|||||||
int ec, swapbytes;
|
int ec, swapbytes;
|
||||||
size_t fsz, i, shnum;
|
size_t fsz, i, shnum;
|
||||||
uint64_t shoff;
|
uint64_t shoff;
|
||||||
uint32_t shtype;
|
|
||||||
char *src;
|
char *src;
|
||||||
Elf32_Ehdr *eh32;
|
Elf32_Ehdr *eh32;
|
||||||
Elf64_Ehdr *eh64;
|
Elf64_Ehdr *eh64;
|
||||||
@ -53,6 +52,7 @@ _libelf_load_scn(Elf *e, void *ehdr)
|
|||||||
|
|
||||||
assert(e != NULL);
|
assert(e != NULL);
|
||||||
assert(ehdr != NULL);
|
assert(ehdr != NULL);
|
||||||
|
assert((e->e_flags & LIBELF_F_SHDRS_LOADED) == 0);
|
||||||
|
|
||||||
#define CHECK_EHDR(E,EH) do { \
|
#define CHECK_EHDR(E,EH) do { \
|
||||||
if (fsz != (EH)->e_shentsize || \
|
if (fsz != (EH)->e_shentsize || \
|
||||||
@ -62,18 +62,18 @@ _libelf_load_scn(Elf *e, void *ehdr)
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
fsz = gelf_fsize(e, ELF_T_SHDR, (size_t) 1, e->e_version);
|
ec = e->e_class;
|
||||||
|
fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, (size_t) 1);
|
||||||
assert(fsz > 0);
|
assert(fsz > 0);
|
||||||
|
|
||||||
ec = e->e_class;
|
shnum = e->e_u.e_elf.e_nscn;
|
||||||
|
|
||||||
if (ec == ELFCLASS32) {
|
if (ec == ELFCLASS32) {
|
||||||
eh32 = (Elf32_Ehdr *) ehdr;
|
eh32 = (Elf32_Ehdr *) ehdr;
|
||||||
shnum = eh32->e_shnum;
|
|
||||||
shoff = (uint64_t) eh32->e_shoff;
|
shoff = (uint64_t) eh32->e_shoff;
|
||||||
CHECK_EHDR(e, eh32);
|
CHECK_EHDR(e, eh32);
|
||||||
} else {
|
} else {
|
||||||
eh64 = (Elf64_Ehdr *) ehdr;
|
eh64 = (Elf64_Ehdr *) ehdr;
|
||||||
shnum = eh64->e_shnum;
|
|
||||||
shoff = eh64->e_shoff;
|
shoff = eh64->e_shoff;
|
||||||
CHECK_EHDR(e, eh64);
|
CHECK_EHDR(e, eh64);
|
||||||
}
|
}
|
||||||
@ -82,32 +82,18 @@ _libelf_load_scn(Elf *e, void *ehdr)
|
|||||||
|
|
||||||
swapbytes = e->e_byteorder != LIBELF_PRIVATE(byteorder);
|
swapbytes = e->e_byteorder != LIBELF_PRIVATE(byteorder);
|
||||||
src = e->e_rawfile + shoff;
|
src = e->e_rawfile + shoff;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the file is using extended numbering then section #0
|
||||||
|
* would have already been read in.
|
||||||
|
*/
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
|
if (!STAILQ_EMPTY(&e->e_u.e_elf.e_scn)) {
|
||||||
|
assert(STAILQ_FIRST(&e->e_u.e_elf.e_scn) ==
|
||||||
|
STAILQ_LAST(&e->e_u.e_elf.e_scn, _Elf_Scn, s_next));
|
||||||
|
|
||||||
if (shnum == (size_t) 0 && shoff != 0LL) {
|
i = 1;
|
||||||
/* Extended section numbering */
|
|
||||||
if ((scn = _libelf_allocate_scn(e, (size_t) 0)) == NULL)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
(*xlator)((char *) &scn->s_shdr, src, (size_t) 1, swapbytes);
|
|
||||||
|
|
||||||
if (ec == ELFCLASS32) {
|
|
||||||
shtype = scn->s_shdr.s_shdr32.sh_type;
|
|
||||||
shnum = scn->s_shdr.s_shdr32.sh_size;
|
|
||||||
} else {
|
|
||||||
shtype = scn->s_shdr.s_shdr64.sh_type;
|
|
||||||
shnum = scn->s_shdr.s_shdr64.sh_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shtype != SHT_NULL) {
|
|
||||||
LIBELF_SET_ERROR(SECTION, 0);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
scn->s_size = 0LL;
|
|
||||||
scn->s_offset = scn->s_rawoff = 0LL;
|
|
||||||
|
|
||||||
i++;
|
|
||||||
src += fsz;
|
src += fsz;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,6 +113,9 @@ _libelf_load_scn(Elf *e, void *ehdr)
|
|||||||
scn->s_size = scn->s_shdr.s_shdr64.sh_size;
|
scn->s_size = scn->s_shdr.s_shdr64.sh_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e->e_flags |= LIBELF_F_SHDRS_LOADED;
|
||||||
|
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +136,8 @@ elf_getscn(Elf *e, size_t index)
|
|||||||
if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL)
|
if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
if (e->e_cmd != ELF_C_WRITE && STAILQ_EMPTY(&e->e_u.e_elf.e_scn) &&
|
if (e->e_cmd != ELF_C_WRITE &&
|
||||||
|
(e->e_flags & LIBELF_F_SHDRS_LOADED) == 0 &&
|
||||||
_libelf_load_scn(e, ehdr) == 0)
|
_libelf_load_scn(e, ehdr) == 0)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
@ -174,7 +164,6 @@ elf_newscn(Elf *e)
|
|||||||
{
|
{
|
||||||
int ec;
|
int ec;
|
||||||
void *ehdr;
|
void *ehdr;
|
||||||
size_t shnum;
|
|
||||||
Elf_Scn *scn;
|
Elf_Scn *scn;
|
||||||
|
|
||||||
if (e == NULL || e->e_kind != ELF_K_ELF) {
|
if (e == NULL || e->e_kind != ELF_K_ELF) {
|
||||||
@ -200,30 +189,25 @@ elf_newscn(Elf *e)
|
|||||||
* file using ELF_C_READ, mess with its internal structure and
|
* file using ELF_C_READ, mess with its internal structure and
|
||||||
* use elf_update(...,ELF_C_NULL) to compute its new layout.
|
* use elf_update(...,ELF_C_NULL) to compute its new layout.
|
||||||
*/
|
*/
|
||||||
if (e->e_cmd != ELF_C_WRITE && STAILQ_EMPTY(&e->e_u.e_elf.e_scn) &&
|
if (e->e_cmd != ELF_C_WRITE &&
|
||||||
|
(e->e_flags & LIBELF_F_SHDRS_LOADED) == 0 &&
|
||||||
_libelf_load_scn(e, ehdr) == 0)
|
_libelf_load_scn(e, ehdr) == 0)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
if (_libelf_getshnum(e, ehdr, ec, &shnum) == 0)
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
if (STAILQ_EMPTY(&e->e_u.e_elf.e_scn)) {
|
if (STAILQ_EMPTY(&e->e_u.e_elf.e_scn)) {
|
||||||
assert(shnum == 0);
|
assert(e->e_u.e_elf.e_nscn == 0);
|
||||||
if ((scn = _libelf_allocate_scn(e, (size_t) SHN_UNDEF)) ==
|
if ((scn = _libelf_allocate_scn(e, (size_t) SHN_UNDEF)) ==
|
||||||
NULL)
|
NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
shnum++;
|
e->e_u.e_elf.e_nscn++;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(shnum > 0);
|
assert(e->e_u.e_elf.e_nscn > 0);
|
||||||
|
|
||||||
if ((scn = _libelf_allocate_scn(e, shnum)) == NULL)
|
if ((scn = _libelf_allocate_scn(e, e->e_u.e_elf.e_nscn)) == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
shnum++;
|
e->e_u.e_elf.e_nscn++;
|
||||||
|
|
||||||
if (_libelf_setshnum(e, ehdr, ec, shnum) == 0)
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
(void) elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY);
|
(void) elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY);
|
||||||
|
|
||||||
|
@ -32,80 +32,6 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#include "_libelf.h"
|
#include "_libelf.h"
|
||||||
|
|
||||||
int
|
|
||||||
_libelf_getshnum(Elf *e, void *eh, int ec, size_t *shnum)
|
|
||||||
{
|
|
||||||
Elf64_Off off;
|
|
||||||
Elf_Scn *scn;
|
|
||||||
void *sh;
|
|
||||||
size_t n;
|
|
||||||
|
|
||||||
if (ec == ELFCLASS32) {
|
|
||||||
n = ((Elf32_Ehdr *) eh)->e_shnum;
|
|
||||||
off = (Elf64_Off) ((Elf32_Ehdr *) eh)->e_shoff;
|
|
||||||
} else {
|
|
||||||
n = ((Elf64_Ehdr *) eh)->e_shnum;
|
|
||||||
off = ((Elf64_Ehdr *) eh)->e_shoff;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n != 0) {
|
|
||||||
*shnum = n;
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (off == 0L) {
|
|
||||||
*shnum = (size_t) 0;
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If 'e_shnum' is zero and 'e_shoff' is non-zero, the file is
|
|
||||||
* using extended section numbering, and the true section
|
|
||||||
* number is kept in the 'sh_size' field of the section header
|
|
||||||
* at offset SHN_UNDEF.
|
|
||||||
*/
|
|
||||||
if ((scn = elf_getscn(e, (size_t) SHN_UNDEF)) == NULL)
|
|
||||||
return (0);
|
|
||||||
if ((sh = _libelf_getshdr(scn, ec)) == NULL)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
if (ec == ELFCLASS32)
|
|
||||||
*shnum = ((Elf32_Shdr *) sh)->sh_size;
|
|
||||||
else
|
|
||||||
*shnum = ((Elf64_Shdr *) sh)->sh_size;
|
|
||||||
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
_libelf_setshnum(Elf *e, void *eh, int ec, size_t shnum)
|
|
||||||
{
|
|
||||||
Elf_Scn *scn;
|
|
||||||
void *sh;
|
|
||||||
|
|
||||||
if (shnum < SHN_LORESERVE) {
|
|
||||||
if (ec == ELFCLASS32)
|
|
||||||
((Elf32_Ehdr *) eh)->e_shnum = shnum;
|
|
||||||
else
|
|
||||||
((Elf64_Ehdr *) eh)->e_shnum = shnum;
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((scn = elf_getscn(e, (size_t) SHN_UNDEF)) == NULL)
|
|
||||||
return (0);
|
|
||||||
if ((sh = _libelf_getshdr(scn, ec)) == NULL)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
if (ec == ELFCLASS32)
|
|
||||||
((Elf32_Shdr *) sh)->sh_size = shnum;
|
|
||||||
else
|
|
||||||
((Elf64_Shdr *) sh)->sh_size = shnum;
|
|
||||||
|
|
||||||
(void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY);
|
|
||||||
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
elf_getshnum(Elf *e, size_t *shnum)
|
elf_getshnum(Elf *e, size_t *shnum)
|
||||||
{
|
{
|
||||||
@ -113,11 +39,15 @@ elf_getshnum(Elf *e, size_t *shnum)
|
|||||||
int ec;
|
int ec;
|
||||||
|
|
||||||
if (e == NULL || e->e_kind != ELF_K_ELF ||
|
if (e == NULL || e->e_kind != ELF_K_ELF ||
|
||||||
((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) ||
|
((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
|
||||||
((eh = _libelf_ehdr(e, ec, 0)) == NULL)) {
|
|
||||||
LIBELF_SET_ERROR(ARGUMENT, 0);
|
LIBELF_SET_ERROR(ARGUMENT, 0);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (_libelf_getshnum(e, eh, ec, shnum));
|
if ((eh = _libelf_ehdr(e, ec, 0)) == NULL)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
*shnum = e->e_u.e_elf.e_nscn;
|
||||||
|
|
||||||
|
return (1);
|
||||||
}
|
}
|
||||||
|
@ -32,68 +32,6 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#include "_libelf.h"
|
#include "_libelf.h"
|
||||||
|
|
||||||
/*
|
|
||||||
* Helpers to get/set the e_shstrndx field of the ELF header.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
_libelf_getshstrndx(Elf *e, void *eh, int ec, size_t *strndx)
|
|
||||||
{
|
|
||||||
Elf_Scn *scn;
|
|
||||||
void *sh;
|
|
||||||
size_t n;
|
|
||||||
|
|
||||||
n = (ec == ELFCLASS32) ? ((Elf32_Ehdr *) eh)->e_shstrndx :
|
|
||||||
((Elf64_Ehdr *) eh)->e_shstrndx;
|
|
||||||
|
|
||||||
if (n < SHN_LORESERVE) {
|
|
||||||
*strndx = n;
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((scn = elf_getscn(e, (size_t) SHN_UNDEF)) == NULL)
|
|
||||||
return (0);
|
|
||||||
if ((sh = _libelf_getshdr(scn, ec)) == NULL)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
if (ec == ELFCLASS32)
|
|
||||||
*strndx = ((Elf32_Shdr *) sh)->sh_link;
|
|
||||||
else
|
|
||||||
*strndx = ((Elf64_Shdr *) sh)->sh_link;
|
|
||||||
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
_libelf_setshstrndx(Elf *e, void *eh, int ec, size_t strndx)
|
|
||||||
{
|
|
||||||
Elf_Scn *scn;
|
|
||||||
void *sh;
|
|
||||||
|
|
||||||
if (strndx < SHN_LORESERVE) {
|
|
||||||
if (ec == ELFCLASS32)
|
|
||||||
((Elf32_Ehdr *) eh)->e_shstrndx = strndx;
|
|
||||||
else
|
|
||||||
((Elf64_Ehdr *) eh)->e_shstrndx = strndx;
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((scn = elf_getscn(e, (size_t) SHN_UNDEF)) == NULL)
|
|
||||||
return (0);
|
|
||||||
if ((sh = _libelf_getshdr(scn, ec)) == NULL)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
if (ec == ELFCLASS32) {
|
|
||||||
((Elf32_Ehdr *) eh)->e_shstrndx = SHN_XINDEX;
|
|
||||||
((Elf32_Shdr *) sh)->sh_link = strndx;
|
|
||||||
} else {
|
|
||||||
((Elf64_Ehdr *) eh)->e_shstrndx = SHN_XINDEX;
|
|
||||||
((Elf64_Shdr *) sh)->sh_link = strndx;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
elf_getshstrndx(Elf *e, size_t *strndx)
|
elf_getshstrndx(Elf *e, size_t *strndx)
|
||||||
{
|
{
|
||||||
@ -101,13 +39,17 @@ elf_getshstrndx(Elf *e, size_t *strndx)
|
|||||||
int ec;
|
int ec;
|
||||||
|
|
||||||
if (e == NULL || e->e_kind != ELF_K_ELF ||
|
if (e == NULL || e->e_kind != ELF_K_ELF ||
|
||||||
((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) ||
|
((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
|
||||||
((eh = _libelf_ehdr(e, ec, 0)) == NULL)) {
|
|
||||||
LIBELF_SET_ERROR(ARGUMENT, 0);
|
LIBELF_SET_ERROR(ARGUMENT, 0);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (_libelf_getshstrndx(e, eh, ec, strndx));
|
if ((eh = _libelf_ehdr(e, ec, 0)) == NULL)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
*strndx = e->e_u.e_elf.e_strndx;
|
||||||
|
|
||||||
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -346,7 +346,6 @@ _libelf_resync_elf(Elf *e)
|
|||||||
if (ec == ELFCLASS32) {
|
if (ec == ELFCLASS32) {
|
||||||
eh_byteorder = eh32->e_ident[EI_DATA];
|
eh_byteorder = eh32->e_ident[EI_DATA];
|
||||||
eh_class = eh32->e_ident[EI_CLASS];
|
eh_class = eh32->e_ident[EI_CLASS];
|
||||||
phnum = eh32->e_phnum;
|
|
||||||
phoff = (uint64_t) eh32->e_phoff;
|
phoff = (uint64_t) eh32->e_phoff;
|
||||||
shoff = (uint64_t) eh32->e_shoff;
|
shoff = (uint64_t) eh32->e_shoff;
|
||||||
eh_type = eh32->e_type;
|
eh_type = eh32->e_type;
|
||||||
@ -354,7 +353,6 @@ _libelf_resync_elf(Elf *e)
|
|||||||
} else {
|
} else {
|
||||||
eh_byteorder = eh64->e_ident[EI_DATA];
|
eh_byteorder = eh64->e_ident[EI_DATA];
|
||||||
eh_class = eh64->e_ident[EI_CLASS];
|
eh_class = eh64->e_ident[EI_CLASS];
|
||||||
phnum = eh64->e_phnum;
|
|
||||||
phoff = eh64->e_phoff;
|
phoff = eh64->e_phoff;
|
||||||
shoff = eh64->e_shoff;
|
shoff = eh64->e_shoff;
|
||||||
eh_type = eh64->e_type;
|
eh_type = eh64->e_type;
|
||||||
@ -379,8 +377,8 @@ _libelf_resync_elf(Elf *e)
|
|||||||
return ((off_t) -1);
|
return ((off_t) -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_libelf_getshnum(e, ehdr, ec, &shnum) == 0)
|
shnum = e->e_u.e_elf.e_nscn;
|
||||||
return ((off_t) -1);
|
phnum = e->e_u.e_elf.e_nphdr;
|
||||||
|
|
||||||
e->e_byteorder = eh_byteorder;
|
e->e_byteorder = eh_byteorder;
|
||||||
|
|
||||||
@ -471,6 +469,13 @@ _libelf_resync_elf(Elf *e)
|
|||||||
} else
|
} else
|
||||||
shoff = 0;
|
shoff = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the fields of the Executable Header that could potentially use
|
||||||
|
* extended numbering.
|
||||||
|
*/
|
||||||
|
_libelf_setphnum(e, ehdr, ec, phnum);
|
||||||
|
_libelf_setshnum(e, ehdr, ec, shnum);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update the `e_phoff' and `e_shoff' fields if the library is
|
* Update the `e_phoff' and `e_shoff' fields if the library is
|
||||||
* doing the layout.
|
* doing the layout.
|
||||||
@ -638,18 +643,17 @@ _libelf_write_elf(Elf *e, off_t newsize)
|
|||||||
ehdr = _libelf_ehdr(e, ec, 0);
|
ehdr = _libelf_ehdr(e, ec, 0);
|
||||||
assert(ehdr != NULL);
|
assert(ehdr != NULL);
|
||||||
|
|
||||||
|
phnum = e->e_u.e_elf.e_nphdr;
|
||||||
|
|
||||||
if (ec == ELFCLASS32) {
|
if (ec == ELFCLASS32) {
|
||||||
eh32 = (Elf32_Ehdr *) ehdr;
|
eh32 = (Elf32_Ehdr *) ehdr;
|
||||||
|
|
||||||
phnum = eh32->e_phnum;
|
|
||||||
phoff = (uint64_t) eh32->e_phoff;
|
phoff = (uint64_t) eh32->e_phoff;
|
||||||
shnum = eh32->e_shnum;
|
shnum = eh32->e_shnum;
|
||||||
shoff = (uint64_t) eh32->e_shoff;
|
shoff = (uint64_t) eh32->e_shoff;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
eh64 = (Elf64_Ehdr *) ehdr;
|
eh64 = (Elf64_Ehdr *) ehdr;
|
||||||
|
|
||||||
phnum = eh64->e_phnum;
|
|
||||||
phoff = eh64->e_phoff;
|
phoff = eh64->e_phoff;
|
||||||
shnum = eh64->e_shnum;
|
shnum = eh64->e_shnum;
|
||||||
shoff = eh64->e_shoff;
|
shoff = eh64->e_shoff;
|
||||||
|
@ -76,7 +76,7 @@ _libelf_checksum(Elf *e, int elfclass)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
checksum = 0;
|
checksum = 0;
|
||||||
for (shn = 1; shn < eh.e_shnum; shn++) {
|
for (shn = 1; shn < e->e_u.e_elf.e_nscn; shn++) {
|
||||||
if ((scn = elf_getscn(e, shn)) == NULL)
|
if ((scn = elf_getscn(e, shn)) == NULL)
|
||||||
return (0);
|
return (0);
|
||||||
if (gelf_getshdr(scn, &shdr) == NULL)
|
if (gelf_getshdr(scn, &shdr) == NULL)
|
||||||
|
@ -36,6 +36,54 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#include "_libelf.h"
|
#include "_libelf.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Retrieve counts for sections, phdrs and the section string table index
|
||||||
|
* from section header #0 of the ELF object.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
_libelf_load_extended(Elf *e, int ec, uint64_t shoff, uint16_t phnum,
|
||||||
|
uint16_t strndx)
|
||||||
|
{
|
||||||
|
Elf_Scn *scn;
|
||||||
|
size_t fsz;
|
||||||
|
void (*xlator)(char *_d, char *_s, size_t _c, int _swap);
|
||||||
|
uint32_t shtype;
|
||||||
|
|
||||||
|
assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn));
|
||||||
|
|
||||||
|
fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, 1);
|
||||||
|
assert(fsz > 0);
|
||||||
|
|
||||||
|
if (e->e_rawsize < shoff + fsz) { /* raw file too small */
|
||||||
|
LIBELF_SET_ERROR(HEADER, 0);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((scn = _libelf_allocate_scn(e, (size_t) 0)) == NULL)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
xlator = _libelf_get_translator(ELF_T_SHDR, ELF_TOMEMORY, ec);
|
||||||
|
(*xlator)((char *) &scn->s_shdr, e->e_rawfile + shoff, (size_t) 1,
|
||||||
|
e->e_byteorder != LIBELF_PRIVATE(byteorder));
|
||||||
|
|
||||||
|
#define GET_SHDR_MEMBER(M) ((ec == ELFCLASS32) ? scn->s_shdr.s_shdr32.M : \
|
||||||
|
scn->s_shdr.s_shdr64.M)
|
||||||
|
|
||||||
|
if ((shtype = GET_SHDR_MEMBER(sh_type)) != SHT_NULL) {
|
||||||
|
LIBELF_SET_ERROR(SECTION, 0);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
e->e_u.e_elf.e_nscn = GET_SHDR_MEMBER(sh_size);
|
||||||
|
e->e_u.e_elf.e_nphdr = (phnum != PN_XNUM) ? phnum :
|
||||||
|
GET_SHDR_MEMBER(sh_info);
|
||||||
|
e->e_u.e_elf.e_strndx = (strndx != SHN_XINDEX) ? strndx :
|
||||||
|
GET_SHDR_MEMBER(sh_link);
|
||||||
|
#undef GET_SHDR_MEMBER
|
||||||
|
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
#define EHDR_INIT(E,SZ) do { \
|
#define EHDR_INIT(E,SZ) do { \
|
||||||
Elf##SZ##_Ehdr *eh = (E); \
|
Elf##SZ##_Ehdr *eh = (E); \
|
||||||
eh->e_ident[EI_MAG0] = ELFMAG0; \
|
eh->e_ident[EI_MAG0] = ELFMAG0; \
|
||||||
@ -53,8 +101,10 @@ __FBSDID("$FreeBSD$");
|
|||||||
void *
|
void *
|
||||||
_libelf_ehdr(Elf *e, int ec, int allocate)
|
_libelf_ehdr(Elf *e, int ec, int allocate)
|
||||||
{
|
{
|
||||||
size_t fsz, msz;
|
|
||||||
void *ehdr;
|
void *ehdr;
|
||||||
|
size_t fsz, msz;
|
||||||
|
uint16_t phnum, shnum, strndx;
|
||||||
|
uint64_t shoff;
|
||||||
void (*xlator)(char *_d, char *_s, size_t _c, int _swap);
|
void (*xlator)(char *_d, char *_s, size_t _c, int _swap);
|
||||||
|
|
||||||
assert(ec == ELFCLASS32 || ec == ELFCLASS64);
|
assert(ec == ELFCLASS32 || ec == ELFCLASS64);
|
||||||
@ -85,8 +135,7 @@ _libelf_ehdr(Elf *e, int ec, int allocate)
|
|||||||
if (ehdr != NULL) /* already have a translated ehdr */
|
if (ehdr != NULL) /* already have a translated ehdr */
|
||||||
return (ehdr);
|
return (ehdr);
|
||||||
|
|
||||||
fsz = gelf_fsize(e, ELF_T_EHDR, (size_t) 1, e->e_version);
|
fsz = _libelf_fsize(ELF_T_EHDR, ec, e->e_version, (size_t) 1);
|
||||||
|
|
||||||
assert(fsz > 0);
|
assert(fsz > 0);
|
||||||
|
|
||||||
if (e->e_cmd != ELF_C_WRITE && e->e_rawsize < fsz) {
|
if (e->e_cmd != ELF_C_WRITE && e->e_rawsize < fsz) {
|
||||||
@ -121,5 +170,35 @@ _libelf_ehdr(Elf *e, int ec, int allocate)
|
|||||||
(*xlator)(ehdr, e->e_rawfile, (size_t) 1,
|
(*xlator)(ehdr, e->e_rawfile, (size_t) 1,
|
||||||
e->e_byteorder != LIBELF_PRIVATE(byteorder));
|
e->e_byteorder != LIBELF_PRIVATE(byteorder));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If extended numbering is being used, read the correct
|
||||||
|
* number of sections and program header entries.
|
||||||
|
*/
|
||||||
|
if (ec == ELFCLASS32) {
|
||||||
|
phnum = ((Elf32_Ehdr *) ehdr)->e_phnum;
|
||||||
|
shnum = ((Elf32_Ehdr *) ehdr)->e_shnum;
|
||||||
|
shoff = ((Elf32_Ehdr *) ehdr)->e_shoff;
|
||||||
|
strndx = ((Elf32_Ehdr *) ehdr)->e_shstrndx;
|
||||||
|
} else {
|
||||||
|
phnum = ((Elf64_Ehdr *) ehdr)->e_phnum;
|
||||||
|
shnum = ((Elf64_Ehdr *) ehdr)->e_shnum;
|
||||||
|
shoff = ((Elf64_Ehdr *) ehdr)->e_shoff;
|
||||||
|
strndx = ((Elf64_Ehdr *) ehdr)->e_shstrndx;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shnum >= SHN_LORESERVE ||
|
||||||
|
(shoff == 0LL && (shnum != 0 || phnum == PN_XNUM ||
|
||||||
|
strndx == SHN_XINDEX))) {
|
||||||
|
LIBELF_SET_ERROR(HEADER, 0);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shnum != 0 || shoff == 0LL) { /* not using extended numbering */
|
||||||
|
e->e_u.e_elf.e_nphdr = phnum;
|
||||||
|
e->e_u.e_elf.e_nscn = shnum;
|
||||||
|
e->e_u.e_elf.e_strndx = strndx;
|
||||||
|
} else if (_libelf_load_extended(e, ec, shoff, phnum, strndx) == 0)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
return (ehdr);
|
return (ehdr);
|
||||||
}
|
}
|
||||||
|
136
lib/libelf/libelf_extended.c
Normal file
136
lib/libelf/libelf_extended.c
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2006 Joseph Koshy
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <libelf.h>
|
||||||
|
|
||||||
|
#include "_libelf.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Retrieve section #0, allocating a new section if needed.
|
||||||
|
*/
|
||||||
|
static Elf_Scn *
|
||||||
|
_libelf_getscn0(Elf *e)
|
||||||
|
{
|
||||||
|
Elf_Scn *s;
|
||||||
|
|
||||||
|
if ((s = STAILQ_FIRST(&e->e_u.e_elf.e_scn)) != NULL)
|
||||||
|
return (s);
|
||||||
|
|
||||||
|
return (_libelf_allocate_scn(e, (size_t) SHN_UNDEF));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_libelf_setshnum(Elf *e, void *eh, int ec, size_t shnum)
|
||||||
|
{
|
||||||
|
Elf_Scn *scn;
|
||||||
|
|
||||||
|
if (shnum >= SHN_LORESERVE) {
|
||||||
|
if ((scn = _libelf_getscn0(e)) == NULL)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
assert(scn->s_ndx == SHN_UNDEF);
|
||||||
|
|
||||||
|
if (ec == ELFCLASS32)
|
||||||
|
scn->s_shdr.s_shdr32.sh_size = shnum;
|
||||||
|
else
|
||||||
|
scn->s_shdr.s_shdr64.sh_size = shnum;
|
||||||
|
|
||||||
|
(void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY);
|
||||||
|
|
||||||
|
shnum = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ec == ELFCLASS32)
|
||||||
|
((Elf32_Ehdr *) eh)->e_shnum = shnum;
|
||||||
|
else
|
||||||
|
((Elf64_Ehdr *) eh)->e_shnum = shnum;
|
||||||
|
|
||||||
|
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_libelf_setshstrndx(Elf *e, void *eh, int ec, size_t shstrndx)
|
||||||
|
{
|
||||||
|
Elf_Scn *scn;
|
||||||
|
|
||||||
|
if (shstrndx >= SHN_LORESERVE) {
|
||||||
|
if ((scn = _libelf_getscn0(e)) == NULL)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
assert(scn->s_ndx == SHN_UNDEF);
|
||||||
|
|
||||||
|
if (ec == ELFCLASS32)
|
||||||
|
scn->s_shdr.s_shdr32.sh_link = shstrndx;
|
||||||
|
else
|
||||||
|
scn->s_shdr.s_shdr64.sh_link = shstrndx;
|
||||||
|
|
||||||
|
(void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY);
|
||||||
|
|
||||||
|
shstrndx = SHN_XINDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ec == ELFCLASS32)
|
||||||
|
((Elf32_Ehdr *) eh)->e_shstrndx = shstrndx;
|
||||||
|
else
|
||||||
|
((Elf64_Ehdr *) eh)->e_shstrndx = shstrndx;
|
||||||
|
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_libelf_setphnum(Elf *e, void *eh, int ec, size_t phnum)
|
||||||
|
{
|
||||||
|
Elf_Scn *scn;
|
||||||
|
|
||||||
|
if (phnum >= PN_XNUM) {
|
||||||
|
if ((scn = _libelf_getscn0(e)) == NULL)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
assert(scn->s_ndx == SHN_UNDEF);
|
||||||
|
|
||||||
|
if (ec == ELFCLASS32)
|
||||||
|
scn->s_shdr.s_shdr32.sh_info = phnum;
|
||||||
|
else
|
||||||
|
scn->s_shdr.s_shdr64.sh_info = phnum;
|
||||||
|
|
||||||
|
(void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY);
|
||||||
|
|
||||||
|
phnum = PN_XNUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ec == ELFCLASS32)
|
||||||
|
((Elf32_Ehdr *) eh)->e_phnum = phnum;
|
||||||
|
else
|
||||||
|
((Elf64_Ehdr *) eh)->e_phnum = phnum;
|
||||||
|
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
@ -66,14 +66,14 @@ _libelf_getphdr(Elf *e, int ec)
|
|||||||
if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL)
|
if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
|
phnum = e->e_u.e_elf.e_nphdr;
|
||||||
|
|
||||||
if (ec == ELFCLASS32) {
|
if (ec == ELFCLASS32) {
|
||||||
eh32 = (Elf32_Ehdr *) ehdr;
|
eh32 = (Elf32_Ehdr *) ehdr;
|
||||||
phnum = eh32->e_phnum;
|
|
||||||
phentsize = eh32->e_phentsize;
|
phentsize = eh32->e_phentsize;
|
||||||
phoff = (uint64_t) eh32->e_phoff;
|
phoff = (uint64_t) eh32->e_phoff;
|
||||||
} else {
|
} else {
|
||||||
eh64 = (Elf64_Ehdr *) ehdr;
|
eh64 = (Elf64_Ehdr *) ehdr;
|
||||||
phnum = eh64->e_phnum;
|
|
||||||
phentsize = eh64->e_phentsize;
|
phentsize = eh64->e_phentsize;
|
||||||
phoff = (uint64_t) eh64->e_phoff;
|
phoff = (uint64_t) eh64->e_phoff;
|
||||||
}
|
}
|
||||||
@ -112,9 +112,7 @@ _libelf_getphdr(Elf *e, int ec)
|
|||||||
void *
|
void *
|
||||||
_libelf_newphdr(Elf *e, int ec, size_t count)
|
_libelf_newphdr(Elf *e, int ec, size_t count)
|
||||||
{
|
{
|
||||||
void *ehdr, *nphdr, *ophdr;
|
void *ehdr, *newphdr, *oldphdr;
|
||||||
Elf32_Ehdr *eh32;
|
|
||||||
Elf64_Ehdr *eh64;
|
|
||||||
size_t msz;
|
size_t msz;
|
||||||
|
|
||||||
if (e == NULL) {
|
if (e == NULL) {
|
||||||
@ -135,31 +133,25 @@ _libelf_newphdr(Elf *e, int ec, size_t count)
|
|||||||
|
|
||||||
assert(msz > 0);
|
assert(msz > 0);
|
||||||
|
|
||||||
nphdr = NULL;
|
newphdr = NULL;
|
||||||
if (count > 0 && (nphdr = calloc(count, msz)) == NULL) {
|
if (count > 0 && (newphdr = calloc(count, msz)) == NULL) {
|
||||||
LIBELF_SET_ERROR(RESOURCE, 0);
|
LIBELF_SET_ERROR(RESOURCE, 0);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ec == ELFCLASS32) {
|
if (ec == ELFCLASS32) {
|
||||||
if ((ophdr = (void *) e->e_u.e_elf.e_phdr.e_phdr32) != NULL)
|
if ((oldphdr = (void *) e->e_u.e_elf.e_phdr.e_phdr32) != NULL)
|
||||||
free(ophdr);
|
free(oldphdr);
|
||||||
e->e_u.e_elf.e_phdr.e_phdr32 = (Elf32_Phdr *) nphdr;
|
e->e_u.e_elf.e_phdr.e_phdr32 = (Elf32_Phdr *) newphdr;
|
||||||
} else {
|
} else {
|
||||||
if ((ophdr = (void *) e->e_u.e_elf.e_phdr.e_phdr64) != NULL)
|
if ((oldphdr = (void *) e->e_u.e_elf.e_phdr.e_phdr64) != NULL)
|
||||||
free(ophdr);
|
free(oldphdr);
|
||||||
e->e_u.e_elf.e_phdr.e_phdr64 = (Elf64_Phdr *) nphdr;
|
e->e_u.e_elf.e_phdr.e_phdr64 = (Elf64_Phdr *) newphdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ec == ELFCLASS32) {
|
e->e_u.e_elf.e_nphdr = count;
|
||||||
eh32 = (Elf32_Ehdr *) ehdr;
|
|
||||||
eh32->e_phnum = count;
|
|
||||||
} else {
|
|
||||||
eh64 = (Elf64_Ehdr *) ehdr;
|
|
||||||
eh64->e_phnum = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
elf_flagphdr(e, ELF_C_SET, ELF_F_DIRTY);
|
elf_flagphdr(e, ELF_C_SET, ELF_F_DIRTY);
|
||||||
|
|
||||||
return (nphdr);
|
return (newphdr);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user