diff --git a/contrib/elftoolchain/libelf/Version.map b/contrib/elftoolchain/libelf/Version.map index e71a59197d0d..3d54bcb90aaa 100644 --- a/contrib/elftoolchain/libelf/Version.map +++ b/contrib/elftoolchain/libelf/Version.map @@ -91,6 +91,13 @@ global: gelf_update_symshndx; gelf_xlatetof; gelf_xlatetom; +}; + +R1.1 { +global: + elf32_getchdr; + elf64_getchdr; + gelf_getchdr; local: *; -}; +} R1.0; diff --git a/contrib/elftoolchain/libelf/_libelf.h b/contrib/elftoolchain/libelf/_libelf.h index 1a70d13886d5..ef1f31a39d61 100644 --- a/contrib/elftoolchain/libelf/_libelf.h +++ b/contrib/elftoolchain/libelf/_libelf.h @@ -220,6 +220,7 @@ size_t _libelf_fsize(Elf_Type _t, int _elfclass, unsigned int _version, size_t count); _libelf_translator_function *_libelf_get_translator(Elf_Type _t, int _direction, int _elfclass, int _elfmachine); +void *_libelf_getchdr(Elf_Scn *_e, int _elfclass); void *_libelf_getphdr(Elf *_e, int _elfclass); void *_libelf_getshdr(Elf_Scn *_scn, int _elfclass); void _libelf_init_elf(Elf *_e, Elf_Kind _kind); diff --git a/contrib/elftoolchain/libelf/gelf.3 b/contrib/elftoolchain/libelf/gelf.3 index d703c1b3f65e..d77fd1083d0b 100644 --- a/contrib/elftoolchain/libelf/gelf.3 +++ b/contrib/elftoolchain/libelf/gelf.3 @@ -23,7 +23,7 @@ .\" .\" $Id: gelf.3 3743 2019-06-12 19:36:30Z jkoshy $ .\" -.Dd June 12, 2019 +.Dd October 23, 2020 .Dt GELF 3 .Os .Sh NAME @@ -45,6 +45,8 @@ The GElf API defines the following class-independent data structures: .Bl -tag -width GElf_Sxword .It Vt GElf_Addr A representation of ELF addresses. +.It Vt GElf_Chdr +A class-independent representation of an ELF Compression Header. .It Vt GElf_Dyn A class-independent representation of ELF .Sy .dynamic @@ -144,6 +146,8 @@ native representation. .El .It "Retrieving ELF Data" .Bl -tag -compact -width indent +.It Fn gelf_getchdr +Retrieve an ELF Compression Header from the underlying ELF descriptor. .It Fn gelf_getdyn Retrieve an ELF .Sy .dynamic diff --git a/contrib/elftoolchain/libelf/gelf.h b/contrib/elftoolchain/libelf/gelf.h index 6eae0a5f27f5..87f272d56204 100644 --- a/contrib/elftoolchain/libelf/gelf.h +++ b/contrib/elftoolchain/libelf/gelf.h @@ -39,6 +39,7 @@ typedef Elf64_Sxword GElf_Sxword; /* Signed long words (64 bit) */ typedef Elf64_Word GElf_Word; /* Unsigned words (32 bit) */ typedef Elf64_Xword GElf_Xword; /* Unsigned long words (64 bit) */ +typedef Elf64_Chdr GElf_Chdr; /* Compressed section header */ typedef Elf64_Dyn GElf_Dyn; /* ".dynamic" section entries */ typedef Elf64_Ehdr GElf_Ehdr; /* ELF header */ typedef Elf64_Phdr GElf_Phdr; /* Program header */ @@ -73,6 +74,7 @@ extern "C" { long gelf_checksum(Elf *_elf); size_t gelf_fsize(Elf *_elf, Elf_Type _type, size_t _count, unsigned int _version); +GElf_Chdr *gelf_getchdr(Elf_Scn *_scn, GElf_Chdr *_dst); int gelf_getclass(Elf *_elf); GElf_Dyn *gelf_getdyn(Elf_Data *_data, int _index, GElf_Dyn *_dst); GElf_Ehdr *gelf_getehdr(Elf *_elf, GElf_Ehdr *_dst); diff --git a/contrib/elftoolchain/libelf/gelf_chdr.c b/contrib/elftoolchain/libelf/gelf_chdr.c new file mode 100644 index 000000000000..9f4f9a699a2a --- /dev/null +++ b/contrib/elftoolchain/libelf/gelf_chdr.c @@ -0,0 +1,82 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 The FreeBSD Foundation + * + * This software was developed by Tiger Gao under sponsorship from + * the FreeBSD Foundation. + * + * 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 +#include +#include +#include +#include + +#include "_libelf.h" + +Elf32_Chdr * +elf32_getchdr(Elf_Scn *s) +{ + return (_libelf_getchdr(s, ELFCLASS32)); +} + +Elf64_Chdr * +elf64_getchdr(Elf_Scn *s) +{ + return (_libelf_getchdr(s, ELFCLASS64)); +} + +GElf_Chdr * +gelf_getchdr(Elf_Scn *s, GElf_Chdr *d) +{ + int ec; + void *ch; + Elf32_Chdr *ch32; + Elf64_Chdr *ch64; + + if (d == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if ((ch = _libelf_getchdr(s, ELFCLASSNONE)) == NULL) + return (NULL); + + ec = s->s_elf->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) { + ch32 = (Elf32_Chdr *)ch; + + d->ch_type = (Elf64_Word)ch32->ch_type; + d->ch_size = (Elf64_Xword)ch32->ch_size; + d->ch_addralign = (Elf64_Xword)ch32->ch_addralign; + } else { + ch64 = (Elf64_Chdr *)ch; + *d = *ch64; + } + + return (d); +} diff --git a/contrib/elftoolchain/libelf/gelf_getchdr.3 b/contrib/elftoolchain/libelf/gelf_getchdr.3 new file mode 100644 index 000000000000..fde9179af3a1 --- /dev/null +++ b/contrib/elftoolchain/libelf/gelf_getchdr.3 @@ -0,0 +1,117 @@ +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.\" Copyright (c) 2020 The FreeBSD Foundation +.\" +.\" This document was written by Tiger Gao under sponsorship from +.\" the FreeBSD Foundation. +.\" +.\" 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. +.\" +.\" $Id: gelf_getchdr.3 3639 2020-10-20 16:07:02Z tig $ +.\" +.Dd October 23, 2020 +.Dt GELF_GETCHDR 3 +.Os +.Sh NAME +.Nm elf32_getchdr , +.Nm elf64_getchdr , +.Nm gelf_getchdr +.Nd retrieve the compression header of a section +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft "Elf32_Chdr *" +.Fn elf32_getchdr "Elf_Scn *s" +.Ft "Elf64_Chdr *" +.Fn elf64_getchdr "Elf_Scn *s" +.In gelf.h +.Ft "GElf_Chdr *" +.Fn gelf_getchdr "Elf_Scn *scn" "GElf_Chdr *chdr" +.Sh DESCRIPTION +These functions return a pointer to the ELF Compression Header data +structure associated with section descriptor +.Ar scn . +.Pp +Function +.Fn elf32_getchdr +retrieves a pointer to an +.Vt Elf32_Chdr +structure. +Section descriptor +.Ar scn +must be associated with an ELF descriptor of class +.Dv ELFCLASS32 . +.Pp +Function +.Fn elf64_getchdr +retrieves a pointer to an +.Vt Elf64_Chdr +structure. +Section descriptor +.Ar scn +must be associated with an ELF descriptor of class +.Dv ELFCLASS64 . +.Pp +Function +.Fn gelf_getchdr +copies the values in the compression header associated with argument +.Ar scn +to the structure pointed to be argument +.Ar dst . +The +.Vt GElf_Chdr +data structure is described in +.Xr gelf 3 . +.Sh RETURN VALUES +Functions +.Fn elf32_getchdr +and +.Fn elf64_getchdr +return a valid pointer to the appropriate compression header on success +or NULL if an error was encountered. +.Pp +Function +.Fn gelf_getchdr +returns argument +.Ar dst +if successful, or NULL if an error was encountered. +.Sh ERRORS +These functions may fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_INVALID_SECTION_FLAGS +Arguments +.Ar scn +has invalid flags. +.It Bq Er ELF_E_INVALID_SECTION_TYPE +Argument +.Ar scn +has invalid type. +.It Bq Er ELF_E_NOT_COMPRESSED +Argument +.Ar scn +is not compressed. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_getscn 3 , +.Xr gelf 3 , diff --git a/contrib/elftoolchain/libelf/libelf.h b/contrib/elftoolchain/libelf/libelf.h index 151651d56473..9fa7035db30c 100644 --- a/contrib/elftoolchain/libelf/libelf.h +++ b/contrib/elftoolchain/libelf/libelf.h @@ -162,6 +162,9 @@ enum Elf_Error { ELF_E_SEQUENCE, /* API calls out of sequence */ ELF_E_UNIMPL, /* Feature is unimplemented */ ELF_E_VERSION, /* Unknown API version */ + ELF_E_INVALID_SECTION_FLAGS, /* Invalid ELF section header flags */ + ELF_E_INVALID_SECTION_TYPE, /* Invalid ELF section header type */ + ELF_E_NOT_COMPRESSED, /* Section is not compressed */ ELF_E_NUM /* Max error number */ }; @@ -227,6 +230,7 @@ unsigned int elf_version(unsigned int _version); long elf32_checksum(Elf *_elf); size_t elf32_fsize(Elf_Type _type, size_t _count, unsigned int _version); +Elf32_Chdr *elf32_getchdr(Elf_Scn *_scn); Elf32_Ehdr *elf32_getehdr(Elf *_elf); Elf32_Phdr *elf32_getphdr(Elf *_elf); Elf32_Shdr *elf32_getshdr(Elf_Scn *_scn); @@ -240,6 +244,7 @@ Elf_Data *elf32_xlatetom(Elf_Data *_dst, const Elf_Data *_src, long elf64_checksum(Elf *_elf); size_t elf64_fsize(Elf_Type _type, size_t _count, unsigned int _version); +Elf64_Chdr *elf64_getchdr(Elf_Scn *_scn); Elf64_Ehdr *elf64_getehdr(Elf *_elf); Elf64_Phdr *elf64_getphdr(Elf *_elf); Elf64_Shdr *elf64_getshdr(Elf_Scn *_scn); diff --git a/contrib/elftoolchain/libelf/libelf_chdr.c b/contrib/elftoolchain/libelf/libelf_chdr.c new file mode 100644 index 000000000000..6a63d4086fc9 --- /dev/null +++ b/contrib/elftoolchain/libelf/libelf_chdr.c @@ -0,0 +1,104 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 The FreeBSD Foundation + * + * This software was developed by Tiger Gao under sponsorship from + * the FreeBSD Foundation. + * + * 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 +#include + +#include "_libelf.h" + +void * +_libelf_getchdr(Elf_Scn *s, int ec) +{ + Elf *e; + void *sh; + Elf32_Shdr *sh32; + Elf64_Shdr *sh64; + + sh32 = NULL; + sh64 = NULL; + + if (s == NULL || (e = s->s_elf) == NULL || e->e_kind != ELF_K_ELF) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (ec == ELFCLASSNONE) { + ec = e->e_class; + } else if (ec != e->e_class) { + LIBELF_SET_ERROR(CLASS, 0); + return (NULL); + } + + if ((sh = _libelf_getshdr(s, ec)) == NULL) { + LIBELF_SET_ERROR(HEADER, 0); + return (NULL); + } + + if (ec == ELFCLASS32) { + sh32 = (Elf32_Shdr *)sh; + if ((sh32->sh_flags & SHF_ALLOC) != 0) { + LIBELF_SET_ERROR(INVALID_SECTION_FLAGS, 0); + return (NULL); + } + + if (sh32->sh_type == SHT_NULL || sh32->sh_type == SHT_NOBITS) { + LIBELF_SET_ERROR(INVALID_SECTION_TYPE, 0); + return (NULL); + } + + if ((sh32->sh_flags & SHF_COMPRESSED) == 0) { + LIBELF_SET_ERROR(NOT_COMPRESSED, 0); + return (NULL); + } + } else { + sh64 = (Elf64_Shdr *)sh; + if ((sh64->sh_flags & SHF_ALLOC) != 0) { + LIBELF_SET_ERROR(INVALID_SECTION_FLAGS, 0); + return (NULL); + } + + if (sh64->sh_type == SHT_NULL || sh64->sh_type == SHT_NOBITS) { + LIBELF_SET_ERROR(INVALID_SECTION_TYPE, 0); + return (NULL); + } + + if ((sh64->sh_flags & SHF_COMPRESSED) == 0) { + LIBELF_SET_ERROR(NOT_COMPRESSED, 0); + return (NULL); + } + } + + Elf_Data *d = elf_getdata(s, NULL); + + if (!d) + return (NULL); + + return ((void *)d->d_buf); +} diff --git a/lib/libelf/Makefile b/lib/libelf/Makefile index f3fd14d1e2b4..8174f4e06bba 100644 --- a/lib/libelf/Makefile +++ b/lib/libelf/Makefile @@ -38,6 +38,7 @@ SRCS= elf.c \ elf_update.c \ elf_version.c \ gelf_cap.c \ + gelf_chdr.c \ gelf_checksum.c \ gelf_dyn.c \ gelf_ehdr.c \ @@ -57,6 +58,7 @@ SRCS= elf.c \ libelf_allocate.c \ libelf_ar.c \ libelf_ar_util.c \ + libelf_chdr.c \ libelf_checksum.c \ libelf_data.c \ libelf_ehdr.c \