1 /* Copyright (C) 2015 Red Hat, Inc.
2 Copyright (C) 2024 Mark J. Wielaard <[email protected]>
3 This file is part of elfutils.
4
5 This file is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 elfutils is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <assert.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <inttypes.h>
27 #include <libelf.h>
28 #include <errno.h>
29 #include <gelf.h>
30 #include <stdbool.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <sys/mman.h>
35
36
37 int
main(int argc,char * argv[])38 main (int argc, char *argv[])
39 {
40 int result = 0;
41 int cnt;
42
43 if (argc < 3
44 || (strcmp (argv[1], "read") != 0
45 && strcmp (argv[1], "mmap") != 0
46 && strcmp (argv[1], "mem") != 0))
47 {
48 printf ("Usage: (read|mmap|mem) files...\n");
49 return -1;
50 }
51
52 bool do_read = strcmp (argv[1], "read") == 0;
53 bool do_mmap = strcmp (argv[1], "mmap") == 0;
54 bool do_mem = strcmp (argv[1], "mem") == 0;
55
56 elf_version (EV_CURRENT);
57
58 for (cnt = 2; cnt < argc; ++cnt)
59 {
60 int fd = open (argv[cnt], O_RDONLY);
61 void *map_address = NULL;
62 size_t map_size = 0;
63
64 Elf *elf;
65 if (do_read)
66 elf = elf_begin (fd, ELF_C_READ, NULL);
67 else if (do_mmap)
68 elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
69 else
70 {
71 assert (do_mem);
72 // We mmap the memory ourselves, explicitly PROT_READ only
73 struct stat st;
74 if (fstat (fd, &st) != 0)
75 {
76 printf ("%s cannot stat %s\n", argv[cnt], strerror (errno));
77 result = 1;
78 close (fd);
79 continue;
80 }
81 map_size = st.st_size;
82 map_address = mmap (NULL, map_size, PROT_READ, MAP_PRIVATE, fd, 0);
83 if (map_address == MAP_FAILED)
84 {
85 printf ("%s cannot mmap %s\n", argv[cnt], strerror (errno));
86 result = 1;
87 close (fd);
88 continue;
89 }
90 if (map_size < EI_NIDENT
91 || memcmp (map_address, ELFMAG, SELFMAG) != 0)
92 {
93 printf ("%s isn't an ELF file\n", argv[cnt]);
94 result = 1;
95 munmap (map_address, map_size);
96 close (fd);
97 continue;
98 }
99 elf = elf_memory (map_address, map_size);
100 }
101 if (elf == NULL)
102 {
103 printf ("%s not usable %s\n", argv[cnt], elf_errmsg (-1));
104 result = 1;
105 close (fd);
106 continue;
107 }
108
109 /* To get the section names. */
110 size_t strndx;
111 elf_getshdrstrndx (elf, &strndx);
112
113 Elf_Scn *scn = NULL;
114 while ((scn = elf_nextscn (elf, scn)) != NULL)
115 {
116 size_t idx = elf_ndxscn (scn);
117 GElf_Shdr mem;
118 GElf_Shdr *shdr = gelf_getshdr (scn, &mem);
119 const char *name = elf_strptr (elf, strndx, shdr->sh_name);
120 if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
121 {
122 /* Real compressed section. */
123 if (elf_compress (scn, 0, 0) < 0)
124 {
125 printf ("elf_compress failed for section %zd: %s\n",
126 idx, elf_errmsg (-1));
127 return -1;
128 }
129 Elf_Data *d = elf_getdata (scn, NULL);
130 printf ("%zd: %s, ELF compressed, size: %zx\n",
131 idx, name, d->d_size);
132 }
133 else
134 {
135 /* Maybe an old GNU compressed .z section? */
136 if (name[0] == '.' && name[1] == 'z')
137 {
138 if (elf_compress_gnu (scn, 0, 0) < 0)
139 {
140 printf ("elf_compress_gnu failed for section %zd: %s\n",
141 idx, elf_errmsg (-1));
142 return -1;
143 }
144 Elf_Data *d = elf_getdata (scn, NULL);
145 printf ("%zd: %s, GNU compressed, size: %zx\n",
146 idx, name, d->d_size);
147 }
148 else
149 printf ("%zd: %s, NOT compressed\n", idx, name);
150 }
151 }
152
153 elf_end (elf);
154 close (fd);
155
156 if (do_mem)
157 {
158 /* Make sure we can still get at the memory. */
159 if (memcmp (map_address, ELFMAG, SELFMAG) != 0)
160 {
161 printf ("%s isn't an ELF file anymore???\n", argv[cnt]);
162 result = 1;
163 }
164 if (munmap (map_address, map_size) != 0)
165 {
166 printf ("%s cannot munmap %s\n", argv[cnt], strerror (errno));
167 result = 1;
168 }
169 }
170 }
171
172 return result;
173 }
174