1 /* Decompression support for libdwfl: zlib (gzip) and/or bzlib (bzip2).
2 Copyright (C) 2009 Red Hat, Inc.
3 This file is part of elfutils.
5 This file is free software; you can redistribute it and/or modify
6 it under the terms of either
8 * the GNU Lesser General Public License as published by the Free
9 Software Foundation; either version 3 of the License, or (at
10 your option) any later version
14 * the GNU General Public License as published by the Free
15 Software Foundation; either version 2 of the License, or (at
16 your option) any later version
18 or both in parallel, as here.
20 elfutils is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
25 You should have received copies of the GNU General Public License and
26 the GNU Lesser General Public License along with this program. If
27 not, see <http://www.gnu.org/licenses/>. */
29 #include "../libelf/libelfP.h"
36 # define __libdw_gunzip(...) false
40 # define __libdw_bunzip2(...) false
44 # define __libdw_unlzma(...) false
47 /* Consumes and replaces *ELF only on success. */
49 decompress (int fd __attribute__ ((unused)), Elf **elf)
51 Dwfl_Error error = DWFL_E_BADELF;
55 #if USE_ZLIB || USE_BZLIB || USE_LZMA
56 const off64_t offset = (*elf)->start_offset;
57 void *const mapped = ((*elf)->map_address == NULL ? NULL
58 : (*elf)->map_address + offset);
59 const size_t mapped_size = (*elf)->maximum_size;
63 error = __libdw_gunzip (fd, offset, mapped, mapped_size, &buffer, &size);
64 if (error == DWFL_E_BADELF)
65 error = __libdw_bunzip2 (fd, offset, mapped, mapped_size, &buffer, &size);
66 if (error == DWFL_E_BADELF)
67 error = __libdw_unlzma (fd, offset, mapped, mapped_size, &buffer, &size);
70 if (error == DWFL_E_NOERROR)
72 if (unlikely (size == 0))
74 error = DWFL_E_BADELF;
79 Elf *memelf = elf_memory (buffer, size);
82 error = DWFL_E_LIBELF;
87 memelf->flags |= ELF_F_MALLOCED;
100 what_kind (int fd, Elf **elfp, Elf_Kind *kind, bool *close_fd)
102 Dwfl_Error error = DWFL_E_NOERROR;
103 *kind = elf_kind (*elfp);
104 if (unlikely (*kind == ELF_K_NONE))
106 if (unlikely (*elfp == NULL))
107 error = DWFL_E_LIBELF;
110 error = decompress (fd, elfp);
111 if (error == DWFL_E_NOERROR)
114 *kind = elf_kind (*elfp);
121 Dwfl_Error internal_function
122 __libdw_open_file (int *fdp, Elf **elfp, bool close_on_fail, bool archive_ok)
124 bool close_fd = false;
126 Elf *elf = elf_begin (*fdp, ELF_C_READ_MMAP_PRIVATE, NULL);
129 Dwfl_Error error = what_kind (*fdp, &elf, &kind, &close_fd);
130 if (error == DWFL_E_BADELF)
132 /* It's not an ELF file or a compressed file.
133 See if it's an image with a header preceding the real file. */
135 off64_t offset = elf->start_offset;
136 error = __libdw_image_header (*fdp, &offset,
137 (elf->map_address == NULL ? NULL
138 : elf->map_address + offset),
140 if (error == DWFL_E_NOERROR)
142 /* Pure evil. libelf needs some better interfaces. */
143 elf->kind = ELF_K_AR;
144 elf->state.ar.elf_ar_hdr.ar_name = "libdwfl is faking you out";
145 elf->state.ar.elf_ar_hdr.ar_size = elf->maximum_size - offset;
146 elf->state.ar.offset = offset - sizeof (struct ar_hdr);
147 Elf *subelf = elf_begin (-1, ELF_C_READ_MMAP_PRIVATE, elf);
148 elf->kind = ELF_K_NONE;
149 if (unlikely (subelf == NULL))
150 error = DWFL_E_LIBELF;
153 subelf->parent = NULL;
154 subelf->flags |= elf->flags & (ELF_F_MMAPPED | ELF_F_MALLOCED);
155 elf->flags &= ~(ELF_F_MMAPPED | ELF_F_MALLOCED);
158 error = what_kind (*fdp, &elf, &kind, &close_fd);
163 if (error == DWFL_E_NOERROR
165 && !(archive_ok && kind == ELF_K_AR))
166 error = DWFL_E_BADELF;
168 if (error != DWFL_E_NOERROR)
174 if (error == DWFL_E_NOERROR ? close_fd : close_on_fail)