Branch data Line data Source code
1 : : /* Linux kernel image support for libdwfl.
2 : : Copyright (C) 2009-2011 Red Hat, Inc.
3 : : Copyright (C) 2022, 2024 Mark J. Wielaard <mark@klomp.org>
4 : : This file is part of elfutils.
5 : :
6 : : This file is free software; you can redistribute it and/or modify
7 : : it under the terms of either
8 : :
9 : : * the GNU Lesser General Public License as published by the Free
10 : : Software Foundation; either version 3 of the License, or (at
11 : : your option) any later version
12 : :
13 : : or
14 : :
15 : : * the GNU General Public License as published by the Free
16 : : Software Foundation; either version 2 of the License, or (at
17 : : your option) any later version
18 : :
19 : : or both in parallel, as here.
20 : :
21 : : elfutils is distributed in the hope that it will be useful, but
22 : : WITHOUT ANY WARRANTY; without even the implied warranty of
23 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 : : General Public License for more details.
25 : :
26 : : You should have received copies of the GNU General Public License and
27 : : the GNU Lesser General Public License along with this program. If
28 : : not, see <http://www.gnu.org/licenses/>. */
29 : :
30 : : #ifdef HAVE_CONFIG_H
31 : : # include <config.h>
32 : : #endif
33 : :
34 : : #include "libdwflP.h"
35 : :
36 : : #if BYTE_ORDER == LITTLE_ENDIAN
37 : : # define LE16(x) (x)
38 : : #else
39 : : # define LE16(x) bswap_16 (x)
40 : : #endif
41 : :
42 : : /* See Documentation/x86/boot.txt in Linux kernel sources
43 : : for an explanation of these format details. */
44 : :
45 : : #define MAGIC1 0xaa55
46 : : #define MAGIC2 0x53726448 /* "HdrS" little-endian */
47 : : #define MIN_VERSION 0x0208
48 : :
49 : : #define H_START (H_SETUP_SECTS & -4)
50 : : #define H_SETUP_SECTS 0x1f1
51 : : #define H_MAGIC1 0x1fe
52 : : #define H_MAGIC2 0x202
53 : : #define H_VERSION 0x206
54 : : #define H_PAYLOAD_OFFSET 0x248
55 : : #define H_PAYLOAD_LENGTH 0x24c
56 : : #define H_END 0x250
57 : : #define H_READ_SIZE (H_END - H_START)
58 : :
59 : : Dwfl_Error
60 : : internal_function
61 : 0 : __libdw_image_header (int fd, off_t *start_offset,
62 : : void *mapped, size_t mapped_size)
63 : : {
64 [ # # ]: 0 : if (likely (mapped_size > H_END))
65 : : {
66 : 0 : const void *header = mapped;
67 : 0 : char header_buffer[H_READ_SIZE + H_START];
68 [ # # ]: 0 : if (header == NULL)
69 : : {
70 : 0 : ssize_t n = pread_retry (fd, header_buffer + H_START, H_READ_SIZE,
71 : 0 : *start_offset + H_START);
72 [ # # ]: 0 : if (n < 0)
73 : 0 : return DWFL_E_ERRNO;
74 [ # # ]: 0 : if (n < H_READ_SIZE)
75 : : return DWFL_E_BADELF;
76 : :
77 : : header = header_buffer;
78 : : }
79 : :
80 : 0 : uint16_t magic1;
81 : 0 : uint32_t magic2;
82 : 0 : uint16_t version;
83 [ # # ]: 0 : memcpy (&magic1, header + H_MAGIC1, sizeof (uint16_t));
84 : 0 : memcpy (&magic2, header + H_MAGIC2, sizeof (uint32_t));
85 : 0 : memcpy (&version, header + H_VERSION, sizeof (uint16_t));
86 [ # # # # ]: 0 : if (magic1 == LE16 (MAGIC1) && magic2 == LE32 (MAGIC2)
87 [ # # ]: 0 : && LE16 (version) >= MIN_VERSION)
88 : : {
89 : : /* The magic numbers match and the version field is sufficient.
90 : : Extract the payload bounds. */
91 : :
92 : 0 : uint32_t offset;
93 : 0 : uint32_t length;
94 : 0 : uint8_t sects;
95 [ # # ]: 0 : memcpy (&offset, header + H_PAYLOAD_OFFSET, sizeof (uint32_t));
96 : 0 : memcpy (&length, header + H_PAYLOAD_LENGTH, sizeof (uint32_t));
97 : 0 : memcpy (§s, header + H_SETUP_SECTS, sizeof (uint8_t));
98 : 0 : offset = LE32 (offset);
99 : 0 : length = LE32 (length);
100 : :
101 [ # # ]: 0 : offset += ((sects ?: 4) + 1) * 512;
102 : :
103 [ # # # # ]: 0 : if (offset > H_END && offset < mapped_size
104 [ # # ]: 0 : && mapped_size - offset >= length)
105 : : {
106 : : /* It looks kosher. Use it! */
107 : 0 : *start_offset += offset;
108 : 0 : return DWFL_E_NOERROR;
109 : : }
110 : : }
111 : : }
112 : : return DWFL_E_BADELF;
113 : : }
|