xref: /aosp_15_r20/external/elfutils/tests/elfgetzdata.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
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