• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Create descriptor for processing file.
2    Copyright (C) 1998-2010, 2012, 2014, 2015, 2016 Red Hat, Inc.
3    This file is part of elfutils.
4    Written by Ulrich Drepper <drepper@redhat.com>, 1998.
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 <assert.h>
35 #include <ctype.h>
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <stdbool.h>
39 #include <stddef.h>
40 #include <string.h>
41 #include <unistd.h>
42 #include <sys/mman.h>
43 #include <sys/stat.h>
44 
45 #include <system.h>
46 #include "libelfP.h"
47 #include "common.h"
48 
49 
50 /* Create descriptor for archive in memory.  */
51 static inline Elf *
file_read_ar(int fildes,void * map_address,off_t offset,size_t maxsize,Elf_Cmd cmd,Elf * parent)52 file_read_ar (int fildes, void *map_address, off_t offset, size_t maxsize,
53 	      Elf_Cmd cmd, Elf *parent)
54 {
55   Elf *elf;
56 
57   /* Create a descriptor.  */
58   elf = allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
59                       ELF_K_AR, 0);
60   if (elf != NULL)
61     {
62       /* We don't read all the symbol tables in advance.  All this will
63 	 happen on demand.  */
64       elf->state.ar.offset = offset + SARMAG;
65 
66       elf->state.ar.elf_ar_hdr.ar_rawname = elf->state.ar.raw_name;
67     }
68 
69   return elf;
70 }
71 
72 
73 static size_t
get_shnum(void * map_address,unsigned char * e_ident,int fildes,int64_t offset,size_t maxsize)74 get_shnum (void *map_address, unsigned char *e_ident, int fildes,
75 	   int64_t offset, size_t maxsize)
76 {
77   size_t result;
78   union
79   {
80     Elf32_Ehdr *e32;
81     Elf64_Ehdr *e64;
82     void *p;
83   } ehdr;
84   union
85   {
86     Elf32_Ehdr e32;
87     Elf64_Ehdr e64;
88   } ehdr_mem;
89   bool is32 = e_ident[EI_CLASS] == ELFCLASS32;
90 
91   if ((is32 && maxsize < sizeof (Elf32_Ehdr))
92       || (!is32 && maxsize < sizeof (Elf64_Ehdr)))
93     {
94        __libelf_seterrno (ELF_E_INVALID_ELF);
95       return (size_t) -1l;
96     }
97 
98   /* Make the ELF header available.  */
99   if (e_ident[EI_DATA] == MY_ELFDATA
100       && (ALLOW_UNALIGNED
101 	  || (((size_t) e_ident
102 	       & ((is32 ? __alignof__ (Elf32_Ehdr) : __alignof__ (Elf64_Ehdr))
103 		  - 1)) == 0)))
104     ehdr.p = e_ident;
105   else
106     {
107       /* We already read the ELF header.  We have to copy the header
108 	 since we possibly modify the data here and the caller
109 	 expects the memory it passes in to be preserved.  */
110       ehdr.p = &ehdr_mem;
111 
112       if (is32)
113 	{
114 	  if (ALLOW_UNALIGNED)
115 	    {
116 	      ehdr_mem.e32.e_shnum = ((Elf32_Ehdr *) e_ident)->e_shnum;
117 	      ehdr_mem.e32.e_shoff = ((Elf32_Ehdr *) e_ident)->e_shoff;
118 	    }
119 	  else
120 	    memcpy (&ehdr_mem, e_ident, sizeof (Elf32_Ehdr));
121 
122 	  if (e_ident[EI_DATA] != MY_ELFDATA)
123 	    {
124 	      CONVERT (ehdr_mem.e32.e_shnum);
125 	      CONVERT (ehdr_mem.e32.e_shoff);
126 	    }
127 	}
128       else
129 	{
130 	  if (ALLOW_UNALIGNED)
131 	    {
132 	      ehdr_mem.e64.e_shnum = ((Elf64_Ehdr *) e_ident)->e_shnum;
133 	      ehdr_mem.e64.e_shoff = ((Elf64_Ehdr *) e_ident)->e_shoff;
134 	    }
135 	  else
136 	    memcpy (&ehdr_mem, e_ident, sizeof (Elf64_Ehdr));
137 
138 	  if (e_ident[EI_DATA] != MY_ELFDATA)
139 	    {
140 	      CONVERT (ehdr_mem.e64.e_shnum);
141 	      CONVERT (ehdr_mem.e64.e_shoff);
142 	    }
143 	}
144     }
145 
146   if (is32)
147     {
148       /* Get the number of sections from the ELF header.  */
149       result = ehdr.e32->e_shnum;
150 
151       if (unlikely (result == 0) && ehdr.e32->e_shoff != 0)
152 	{
153 	  if (unlikely (ehdr.e32->e_shoff >= maxsize)
154 	      || unlikely (maxsize - ehdr.e32->e_shoff < sizeof (Elf32_Shdr)))
155 	    /* Cannot read the first section header.  */
156 	    return 0;
157 
158 	  if (likely (map_address != NULL) && e_ident[EI_DATA] == MY_ELFDATA
159 	      && (ALLOW_UNALIGNED
160 		  || (((size_t) ((char *) map_address + ehdr.e32->e_shoff))
161 		      & (__alignof__ (Elf32_Shdr) - 1)) == 0))
162 	    /* We can directly access the memory.  */
163 	    result = ((Elf32_Shdr *) ((char *) map_address + ehdr.e32->e_shoff
164 				      + offset))->sh_size;
165 	  else
166 	    {
167 	      Elf32_Word size;
168 	      ssize_t r;
169 
170 	      if (likely (map_address != NULL))
171 		/* gcc will optimize the memcpy to a simple memory
172 		   access while taking care of alignment issues.  */
173 		memcpy (&size, &((Elf32_Shdr *) ((char *) map_address
174 						 + ehdr.e32->e_shoff
175 						 + offset))->sh_size,
176 			sizeof (Elf32_Word));
177 	      else
178 		if (unlikely ((r = pread_retry (fildes, &size,
179 						sizeof (Elf32_Word),
180 						offset + ehdr.e32->e_shoff
181 						+ offsetof (Elf32_Shdr,
182 							    sh_size)))
183 			      != sizeof (Elf32_Word)))
184 		  {
185 		    if (r < 0)
186 		      __libelf_seterrno (ELF_E_INVALID_FILE);
187 		    else
188 		      __libelf_seterrno (ELF_E_INVALID_ELF);
189 		    return (size_t) -1l;
190 		  }
191 
192 	      if (e_ident[EI_DATA] != MY_ELFDATA)
193 		CONVERT (size);
194 
195 	      result = size;
196 	    }
197 	}
198 
199       /* If the section headers were truncated, pretend none were there.  */
200       if (ehdr.e32->e_shoff > maxsize
201 	  || maxsize - ehdr.e32->e_shoff < sizeof (Elf32_Shdr) * result)
202 	result = 0;
203     }
204   else
205     {
206       /* Get the number of sections from the ELF header.  */
207       result = ehdr.e64->e_shnum;
208 
209       if (unlikely (result == 0) && ehdr.e64->e_shoff != 0)
210 	{
211 	  if (unlikely (ehdr.e64->e_shoff >= maxsize)
212 	      || unlikely (ehdr.e64->e_shoff + sizeof (Elf64_Shdr) > maxsize))
213 	    /* Cannot read the first section header.  */
214 	    return 0;
215 
216 	  Elf64_Xword size;
217 	  if (likely (map_address != NULL) && e_ident[EI_DATA] == MY_ELFDATA
218 	      && (ALLOW_UNALIGNED
219 		  || (((size_t) ((char *) map_address + ehdr.e64->e_shoff))
220 		      & (__alignof__ (Elf64_Shdr) - 1)) == 0))
221 	    /* We can directly access the memory.  */
222 	    size = ((Elf64_Shdr *) ((char *) map_address + ehdr.e64->e_shoff
223 				    + offset))->sh_size;
224 	  else
225 	    {
226 	      ssize_t r;
227 	      if (likely (map_address != NULL))
228 		/* gcc will optimize the memcpy to a simple memory
229 		   access while taking care of alignment issues.  */
230 		memcpy (&size, &((Elf64_Shdr *) ((char *) map_address
231 						 + ehdr.e64->e_shoff
232 						 + offset))->sh_size,
233 			sizeof (Elf64_Xword));
234 	      else
235 		if (unlikely ((r = pread_retry (fildes, &size,
236 						sizeof (Elf64_Xword),
237 						offset + ehdr.e64->e_shoff
238 						+ offsetof (Elf64_Shdr,
239 							    sh_size)))
240 			      != sizeof (Elf64_Xword)))
241 		  {
242 		    if (r < 0)
243 		      __libelf_seterrno (ELF_E_INVALID_FILE);
244 		    else
245 		      __libelf_seterrno (ELF_E_INVALID_ELF);
246 		    return (size_t) -1l;
247 		  }
248 
249 	      if (e_ident[EI_DATA] != MY_ELFDATA)
250 		CONVERT (size);
251 	    }
252 
253 	  /* Although sh_size is an Elf64_Xword and can contain a 64bit
254 	     value, we only expect an 32bit value max.  GElf_Word is
255 	     32bit unsigned.  */
256 	  if (size > ~((GElf_Word) 0))
257 	    {
258 	      /* Invalid value, it is too large.  */
259 	      __libelf_seterrno (ELF_E_INVALID_ELF);
260 	      return (size_t) -1l;
261 	    }
262 
263 	  result = size;
264 	}
265 
266       /* If the section headers were truncated, pretend none were there.  */
267       if (ehdr.e64->e_shoff > maxsize
268 	  || maxsize - ehdr.e64->e_shoff < sizeof (Elf64_Shdr) * result)
269 	result = 0;
270     }
271 
272   return result;
273 }
274 
275 
276 /* Create descriptor for ELF file in memory.  */
277 static Elf *
file_read_elf(int fildes,void * map_address,unsigned char * e_ident,int64_t offset,size_t maxsize,Elf_Cmd cmd,Elf * parent)278 file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
279 	       int64_t offset, size_t maxsize, Elf_Cmd cmd, Elf *parent)
280 {
281   /* Verify the binary is of the class we can handle.  */
282   if (unlikely ((e_ident[EI_CLASS] != ELFCLASS32
283 		 && e_ident[EI_CLASS] != ELFCLASS64)
284 		/* We also can only handle two encodings.  */
285 		|| (e_ident[EI_DATA] != ELFDATA2LSB
286 		    && e_ident[EI_DATA] != ELFDATA2MSB)))
287     {
288       /* Cannot handle this.  */
289       __libelf_seterrno (ELF_E_INVALID_ELF);
290       return NULL;
291     }
292 
293   /* Determine the number of sections.  Returns -1 and sets libelf errno
294      if the file handle or elf file is invalid.  Returns zero if there
295      are no section headers (or they cannot be read).  */
296   size_t scncnt = get_shnum (map_address, e_ident, fildes, offset, maxsize);
297   if (scncnt == (size_t) -1l)
298     /* Could not determine the number of sections.  */
299     return NULL;
300 
301   /* Check for too many sections.  */
302   if (e_ident[EI_CLASS] == ELFCLASS32)
303     {
304       if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf32_Shdr)))
305 	{
306 	  __libelf_seterrno (ELF_E_INVALID_ELF);
307 	  return NULL;
308 	}
309     }
310   else if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf64_Shdr)))
311     {
312       __libelf_seterrno (ELF_E_INVALID_ELF);
313       return NULL;
314     }
315 
316   /* We can now allocate the memory.  Even if there are no section headers,
317      we allocate space for a zeroth section in case we need it later.  */
318   const size_t scnmax = (scncnt ?: (cmd == ELF_C_RDWR || cmd == ELF_C_RDWR_MMAP)
319 			 ? 1 : 0);
320   Elf *elf = allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
321 			   ELF_K_ELF, scnmax * sizeof (Elf_Scn));
322   if (elf == NULL)
323     /* Not enough memory.  allocate_elf will have set libelf errno.  */
324     return NULL;
325 
326   assert ((unsigned int) scncnt == scncnt);
327   assert (offsetof (struct Elf, state.elf32.scns)
328 	  == offsetof (struct Elf, state.elf64.scns));
329   elf->state.elf32.scns.cnt = scncnt;
330   elf->state.elf32.scns.max = scnmax;
331 
332   /* Some more or less arbitrary value.  */
333   elf->state.elf.scnincr = 10;
334 
335   /* Make the class easily available.  */
336   elf->class = e_ident[EI_CLASS];
337 
338   if (e_ident[EI_CLASS] == ELFCLASS32)
339     {
340       /* This pointer might not be directly usable if the alignment is
341 	 not sufficient for the architecture.  */
342       Elf32_Ehdr *ehdr = (Elf32_Ehdr *) ((char *) map_address + offset);
343 
344       /* This is a 32-bit binary.  */
345       if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
346 	  && (ALLOW_UNALIGNED
347 	      || (((uintptr_t) ehdr) & (__alignof__ (Elf32_Ehdr) - 1)) == 0))
348 	{
349 	  /* We can use the mmapped memory.  */
350 	  elf->state.elf32.ehdr = ehdr;
351 	}
352       else
353 	{
354 	  /* Copy the ELF header.  */
355 	  elf->state.elf32.ehdr = memcpy (&elf->state.elf32.ehdr_mem, e_ident,
356 					  sizeof (Elf32_Ehdr));
357 
358 	  if (e_ident[EI_DATA] != MY_ELFDATA)
359 	    {
360 	      CONVERT (elf->state.elf32.ehdr_mem.e_type);
361 	      CONVERT (elf->state.elf32.ehdr_mem.e_machine);
362 	      CONVERT (elf->state.elf32.ehdr_mem.e_version);
363 	      CONVERT (elf->state.elf32.ehdr_mem.e_entry);
364 	      CONVERT (elf->state.elf32.ehdr_mem.e_phoff);
365 	      CONVERT (elf->state.elf32.ehdr_mem.e_shoff);
366 	      CONVERT (elf->state.elf32.ehdr_mem.e_flags);
367 	      CONVERT (elf->state.elf32.ehdr_mem.e_ehsize);
368 	      CONVERT (elf->state.elf32.ehdr_mem.e_phentsize);
369 	      CONVERT (elf->state.elf32.ehdr_mem.e_phnum);
370 	      CONVERT (elf->state.elf32.ehdr_mem.e_shentsize);
371 	      CONVERT (elf->state.elf32.ehdr_mem.e_shnum);
372 	      CONVERT (elf->state.elf32.ehdr_mem.e_shstrndx);
373 	    }
374 	}
375 
376       /* Don't precache the phdr pointer here.
377 	 elf32_getphdr will validate it against the size when asked.  */
378 
379       Elf32_Off e_shoff = elf->state.elf32.ehdr->e_shoff;
380       if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
381 	  && cmd != ELF_C_READ_MMAP /* We need a copy to be able to write.  */
382 	  && (ALLOW_UNALIGNED
383 	      || (((uintptr_t) ((char *) ehdr + e_shoff)
384 		   & (__alignof__ (Elf32_Shdr) - 1)) == 0)))
385 	{
386 	  if (unlikely (scncnt > 0 && e_shoff >= maxsize)
387 	      || unlikely (maxsize - e_shoff
388 			   < scncnt * sizeof (Elf32_Shdr)))
389 	    {
390 	    free_and_out:
391 	      free (elf);
392 	      __libelf_seterrno (ELF_E_INVALID_ELF);
393 	      return NULL;
394 	    }
395 	  elf->state.elf32.shdr
396 	    = (Elf32_Shdr *) ((char *) ehdr + e_shoff);
397 
398 	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
399 	    {
400 	      elf->state.elf32.scns.data[cnt].index = cnt;
401 	      elf->state.elf32.scns.data[cnt].elf = elf;
402 	      elf->state.elf32.scns.data[cnt].shdr.e32 =
403 		&elf->state.elf32.shdr[cnt];
404 	      if (likely (elf->state.elf32.shdr[cnt].sh_offset < maxsize)
405 		  && likely (elf->state.elf32.shdr[cnt].sh_size
406 			     <= maxsize - elf->state.elf32.shdr[cnt].sh_offset))
407 		elf->state.elf32.scns.data[cnt].rawdata_base =
408 		  elf->state.elf32.scns.data[cnt].data_base =
409 		  ((char *) map_address + offset
410 		   + elf->state.elf32.shdr[cnt].sh_offset);
411 	      elf->state.elf32.scns.data[cnt].list = &elf->state.elf32.scns;
412 
413 	      /* If this is a section with an extended index add a
414 		 reference in the section which uses the extended
415 		 index.  */
416 	      if (elf->state.elf32.shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
417 		  && elf->state.elf32.shdr[cnt].sh_link < scncnt)
418 		elf->state.elf32.scns.data[elf->state.elf32.shdr[cnt].sh_link].shndx_index
419 		  = cnt;
420 
421 	      /* Set the own shndx_index field in case it has not yet
422 		 been set.  */
423 	      if (elf->state.elf32.scns.data[cnt].shndx_index == 0)
424 		elf->state.elf32.scns.data[cnt].shndx_index = -1;
425 	    }
426 	}
427       else
428 	{
429 	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
430 	    {
431 	      elf->state.elf32.scns.data[cnt].index = cnt;
432 	      elf->state.elf32.scns.data[cnt].elf = elf;
433 	      elf->state.elf32.scns.data[cnt].list = &elf->state.elf32.scns;
434 	    }
435 	}
436 
437       /* So far only one block with sections.  */
438       elf->state.elf32.scns_last = &elf->state.elf32.scns;
439     }
440   else
441     {
442       /* This pointer might not be directly usable if the alignment is
443 	 not sufficient for the architecture.  */
444       Elf64_Ehdr *ehdr = (Elf64_Ehdr *) ((char *) map_address + offset);
445 
446       /* This is a 64-bit binary.  */
447       if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
448 	  && (ALLOW_UNALIGNED
449 	      || (((uintptr_t) ehdr) & (__alignof__ (Elf64_Ehdr) - 1)) == 0))
450 	{
451 	  /* We can use the mmapped memory.  */
452 	  elf->state.elf64.ehdr = ehdr;
453 	}
454       else
455 	{
456 	  /* Copy the ELF header.  */
457 	  elf->state.elf64.ehdr = memcpy (&elf->state.elf64.ehdr_mem, e_ident,
458 					  sizeof (Elf64_Ehdr));
459 
460 	  if (e_ident[EI_DATA] != MY_ELFDATA)
461 	    {
462 	      CONVERT (elf->state.elf64.ehdr_mem.e_type);
463 	      CONVERT (elf->state.elf64.ehdr_mem.e_machine);
464 	      CONVERT (elf->state.elf64.ehdr_mem.e_version);
465 	      CONVERT (elf->state.elf64.ehdr_mem.e_entry);
466 	      CONVERT (elf->state.elf64.ehdr_mem.e_phoff);
467 	      CONVERT (elf->state.elf64.ehdr_mem.e_shoff);
468 	      CONVERT (elf->state.elf64.ehdr_mem.e_flags);
469 	      CONVERT (elf->state.elf64.ehdr_mem.e_ehsize);
470 	      CONVERT (elf->state.elf64.ehdr_mem.e_phentsize);
471 	      CONVERT (elf->state.elf64.ehdr_mem.e_phnum);
472 	      CONVERT (elf->state.elf64.ehdr_mem.e_shentsize);
473 	      CONVERT (elf->state.elf64.ehdr_mem.e_shnum);
474 	      CONVERT (elf->state.elf64.ehdr_mem.e_shstrndx);
475 	    }
476 	}
477 
478       /* Don't precache the phdr pointer here.
479 	 elf64_getphdr will validate it against the size when asked.  */
480 
481       Elf64_Off e_shoff = elf->state.elf64.ehdr->e_shoff;
482       if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
483 	  && cmd != ELF_C_READ_MMAP /* We need a copy to be able to write.  */
484 	  && (ALLOW_UNALIGNED
485 	      || (((uintptr_t) ((char *) ehdr + e_shoff)
486 		   & (__alignof__ (Elf64_Shdr) - 1)) == 0)))
487 	{
488 	  if (unlikely (scncnt > 0 && e_shoff >= maxsize)
489 	      || unlikely (maxsize - e_shoff
490 			   < scncnt * sizeof (Elf64_Shdr)))
491 	    goto free_and_out;
492 	  elf->state.elf64.shdr
493 	    = (Elf64_Shdr *) ((char *) ehdr + e_shoff);
494 
495 	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
496 	    {
497 	      elf->state.elf64.scns.data[cnt].index = cnt;
498 	      elf->state.elf64.scns.data[cnt].elf = elf;
499 	      elf->state.elf64.scns.data[cnt].shdr.e64 =
500 		&elf->state.elf64.shdr[cnt];
501 	      if (likely (elf->state.elf64.shdr[cnt].sh_offset < maxsize)
502 		  && likely (elf->state.elf64.shdr[cnt].sh_size
503 			     <= maxsize - elf->state.elf64.shdr[cnt].sh_offset))
504 		elf->state.elf64.scns.data[cnt].rawdata_base =
505 		  elf->state.elf64.scns.data[cnt].data_base =
506 		  ((char *) map_address + offset
507 		   + elf->state.elf64.shdr[cnt].sh_offset);
508 	      elf->state.elf64.scns.data[cnt].list = &elf->state.elf64.scns;
509 
510 	      /* If this is a section with an extended index add a
511 		 reference in the section which uses the extended
512 		 index.  */
513 	      if (elf->state.elf64.shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
514 		  && elf->state.elf64.shdr[cnt].sh_link < scncnt)
515 		elf->state.elf64.scns.data[elf->state.elf64.shdr[cnt].sh_link].shndx_index
516 		  = cnt;
517 
518 	      /* Set the own shndx_index field in case it has not yet
519 		 been set.  */
520 	      if (elf->state.elf64.scns.data[cnt].shndx_index == 0)
521 		elf->state.elf64.scns.data[cnt].shndx_index = -1;
522 	    }
523 	}
524       else
525 	{
526 	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
527 	    {
528 	      elf->state.elf64.scns.data[cnt].index = cnt;
529 	      elf->state.elf64.scns.data[cnt].elf = elf;
530 	      elf->state.elf64.scns.data[cnt].list = &elf->state.elf64.scns;
531 	    }
532 	}
533 
534       /* So far only one block with sections.  */
535       elf->state.elf64.scns_last = &elf->state.elf64.scns;
536     }
537 
538   return elf;
539 }
540 
541 
542 Elf *
543 internal_function
__libelf_read_mmaped_file(int fildes,void * map_address,int64_t offset,size_t maxsize,Elf_Cmd cmd,Elf * parent)544 __libelf_read_mmaped_file (int fildes, void *map_address,  int64_t offset,
545 			   size_t maxsize, Elf_Cmd cmd, Elf *parent)
546 {
547   /* We have to find out what kind of file this is.  We handle ELF
548      files and archives.  To find out what we have we must look at the
549      header.  The header for an ELF file is EI_NIDENT bytes in size,
550      the header for an archive file SARMAG bytes long.  */
551   unsigned char *e_ident = (unsigned char *) map_address + offset;
552 
553   /* See what kind of object we have here.  */
554   Elf_Kind kind = determine_kind (e_ident, maxsize);
555 
556   switch (kind)
557     {
558     case ELF_K_ELF:
559       return file_read_elf (fildes, map_address, e_ident, offset, maxsize,
560 			    cmd, parent);
561 
562     case ELF_K_AR:
563       return file_read_ar (fildes, map_address, offset, maxsize, cmd, parent);
564 
565     default:
566       break;
567     }
568 
569   /* This case is easy.  Since we cannot do anything with this file
570      create a dummy descriptor.  */
571   return allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
572 		       ELF_K_NONE, 0);
573 }
574 
575 
576 static Elf *
read_unmmaped_file(int fildes,int64_t offset,size_t maxsize,Elf_Cmd cmd,Elf * parent)577 read_unmmaped_file (int fildes, int64_t offset, size_t maxsize, Elf_Cmd cmd,
578 		    Elf *parent)
579 {
580   /* We have to find out what kind of file this is.  We handle ELF
581      files and archives.  To find out what we have we must read the
582      header.  The identification header for an ELF file is EI_NIDENT
583      bytes in size, but we read the whole ELF header since we will
584      need it anyway later.  For archives the header in SARMAG bytes
585      long.  Read the maximum of these numbers.
586 
587      XXX We have to change this for the extended `ar' format some day.
588 
589      Use a union to ensure alignment.  We might later access the
590      memory as a ElfXX_Ehdr.  */
591   union
592   {
593     Elf64_Ehdr ehdr;
594     unsigned char header[MAX (sizeof (Elf64_Ehdr), SARMAG)];
595   } mem;
596 
597   /* Read the head of the file.  */
598   ssize_t nread = pread_retry (fildes, mem.header,
599 			       MIN (MAX (sizeof (Elf64_Ehdr), SARMAG),
600 				    maxsize),
601 			       offset);
602   if (unlikely (nread == -1))
603     {
604       /* We cannot even read the head of the file.  Maybe FILDES is associated
605 	 with an unseekable device.  This is nothing we can handle.  */
606       __libelf_seterrno (ELF_E_INVALID_FILE);
607       return NULL;
608     }
609 
610   /* See what kind of object we have here.  */
611   Elf_Kind kind = determine_kind (mem.header, nread);
612 
613   switch (kind)
614     {
615     case ELF_K_AR:
616       return file_read_ar (fildes, NULL, offset, maxsize, cmd, parent);
617 
618     case ELF_K_ELF:
619       /* Make sure at least the ELF header is contained in the file.  */
620       if ((size_t) nread >= (mem.header[EI_CLASS] == ELFCLASS32
621 			     ? sizeof (Elf32_Ehdr) : sizeof (Elf64_Ehdr)))
622 	return file_read_elf (fildes, NULL, mem.header, offset, maxsize, cmd,
623 			      parent);
624       FALLTHROUGH;
625 
626     default:
627       break;
628     }
629 
630   /* This case is easy.  Since we cannot do anything with this file
631      create a dummy descriptor.  */
632   return allocate_elf (fildes, NULL, offset, maxsize, cmd, parent,
633 		       ELF_K_NONE, 0);
634 }
635 
636 
637 /* Open a file for reading.  If possible we will try to mmap() the file.  */
638 static struct Elf *
read_file(int fildes,int64_t offset,size_t maxsize,Elf_Cmd cmd,Elf * parent)639 read_file (int fildes, int64_t offset, size_t maxsize,
640 	   Elf_Cmd cmd, Elf *parent)
641 {
642   void *map_address = NULL;
643   int use_mmap = (cmd == ELF_C_READ_MMAP || cmd == ELF_C_RDWR_MMAP
644 		  || cmd == ELF_C_WRITE_MMAP
645 		  || cmd == ELF_C_READ_MMAP_PRIVATE);
646 
647   if (parent == NULL)
648     {
649       if (maxsize == ~((size_t) 0))
650 	{
651 	  /* We don't know in the moment how large the file is.
652 	     Determine it now.  */
653 	  struct stat st;
654 
655 	  if (fstat (fildes, &st) == 0
656 	      && (sizeof (size_t) >= sizeof (st.st_size)
657 		  || st.st_size <= ~((size_t) 0)))
658 	    maxsize = (size_t) st.st_size;
659 	}
660     }
661   else
662     {
663       /* The parent is already loaded.  Use it.  */
664       assert (maxsize != ~((size_t) 0));
665     }
666 
667   if (use_mmap)
668     {
669       if (parent == NULL)
670 	{
671 	  /* We try to map the file ourself.  */
672 	  map_address = mmap (NULL, maxsize, (cmd == ELF_C_READ_MMAP
673 					      ? PROT_READ
674 					      : PROT_READ|PROT_WRITE),
675 			      cmd == ELF_C_READ_MMAP_PRIVATE
676 			      || cmd == ELF_C_READ_MMAP
677 			      ? MAP_PRIVATE : MAP_SHARED,
678 			      fildes, offset);
679 
680 	  if (map_address == MAP_FAILED)
681 	    map_address = NULL;
682 	}
683       else
684 	{
685 	  map_address = parent->map_address;
686 	}
687     }
688 
689   /* If we have the file in memory optimize the access.  */
690   if (map_address != NULL)
691     {
692       assert (map_address != MAP_FAILED);
693 
694       struct Elf *result = __libelf_read_mmaped_file (fildes, map_address,
695 						      offset, maxsize, cmd,
696 						      parent);
697 
698       /* If something went wrong during the initialization unmap the
699 	 memory if we mmaped here.  */
700       if (result == NULL
701 	  && (parent == NULL
702 	      || parent->map_address != map_address))
703 	munmap (map_address, maxsize);
704       else if (parent == NULL)
705 	/* Remember that we mmap()ed the memory.  */
706 	result->flags |= ELF_F_MMAPPED;
707 
708       return result;
709     }
710 
711   /* Otherwise we have to do it the hard way.  We read as much as necessary
712      from the file whenever we need information which is not available.  */
713   return read_unmmaped_file (fildes, offset, maxsize, cmd, parent);
714 }
715 
716 
717 /* Find the entry with the long names for the content of this archive.  */
718 static const char *
read_long_names(Elf * elf)719 read_long_names (Elf *elf)
720 {
721   off_t offset = SARMAG;	/* This is the first entry.  */
722   struct ar_hdr hdrm;
723   struct ar_hdr *hdr;
724   char *newp;
725   size_t len;
726 
727   while (1)
728     {
729       if (elf->map_address != NULL)
730 	{
731 	  if ((size_t) offset > elf->maximum_size
732 	      || elf->maximum_size - offset < sizeof (struct ar_hdr))
733 	    return NULL;
734 
735 	  /* The data is mapped.  */
736 	  hdr = (struct ar_hdr *) (elf->map_address + offset);
737 	}
738       else
739 	{
740 	  /* Read the header from the file.  */
741 	  if (unlikely (pread_retry (elf->fildes, &hdrm, sizeof (hdrm),
742 				     elf->start_offset + offset)
743 			!= sizeof (hdrm)))
744 	    return NULL;
745 
746 	  hdr = &hdrm;
747 	}
748 
749       /* The ar_size is given as a fixed size decimal string, right
750 	 padded with spaces.  Make sure we read it properly even if
751 	 there is no terminating space.  */
752       char buf[sizeof (hdr->ar_size) + 1];
753       const char *string = hdr->ar_size;
754       if (hdr->ar_size[sizeof (hdr->ar_size) - 1] != ' ')
755 	{
756 	  *((char *) mempcpy (buf, hdr->ar_size, sizeof (hdr->ar_size))) = '\0';
757 	  string = buf;
758 	}
759       len = atol (string);
760 
761       if (memcmp (hdr->ar_name, "//              ", 16) == 0)
762 	break;
763 
764       offset += sizeof (struct ar_hdr) + ((len + 1) & ~1l);
765     }
766 
767   /* Sanity check len early if we can.  */
768   if (elf->map_address != NULL)
769     {
770       if (len > elf->maximum_size - offset - sizeof (struct ar_hdr))
771 	return NULL;
772     }
773 
774   /* Due to the stupid format of the long name table entry (which are not
775      NUL terminted) we have to provide an appropriate representation anyhow.
776      Therefore we always make a copy which has the appropriate form.  */
777   newp = (char *) malloc (len);
778   if (newp != NULL)
779     {
780       char *runp;
781 
782       if (elf->map_address != NULL)
783 	{
784 	  /* Simply copy it over.  */
785 	  elf->state.ar.long_names = (char *) memcpy (newp,
786 						      elf->map_address + offset
787 						      + sizeof (struct ar_hdr),
788 						      len);
789 	}
790       else
791 	{
792 	  if (unlikely ((size_t) pread_retry (elf->fildes, newp, len,
793 					      elf->start_offset + offset
794 					      + sizeof (struct ar_hdr))
795 			!= len))
796 	    {
797 	      /* We were not able to read all data.  */
798 	      free (newp);
799 	      elf->state.ar.long_names = NULL;
800 	      return NULL;
801 	    }
802 	  elf->state.ar.long_names = newp;
803 	}
804 
805       elf->state.ar.long_names_len = len;
806 
807       /* Now NUL-terminate the strings.  */
808       runp = newp;
809       while (1)
810         {
811 	  char *startp = runp;
812 	  runp = (char *) memchr (runp, '/', newp + len - runp);
813 	  if (runp == NULL)
814 	    {
815 	      /* This was the last entry.  Clear any left overs.  */
816 	      memset (startp, '\0', newp + len - startp);
817 	      break;
818 	    }
819 
820 	  /* NUL-terminate the string.  */
821 	  *runp++ = '\0';
822 
823 	  /* A sanity check.  Somebody might have generated invalid
824 	     archive.  */
825 	  if (runp >= newp + len)
826 	    break;
827 	}
828     }
829 
830   return newp;
831 }
832 
833 
834 /* Read the next archive header.  */
835 int
836 internal_function
__libelf_next_arhdr_wrlock(Elf * elf)837 __libelf_next_arhdr_wrlock (Elf *elf)
838 {
839   struct ar_hdr *ar_hdr;
840   Elf_Arhdr *elf_ar_hdr;
841 
842   if (elf->map_address != NULL)
843     {
844       /* See whether this entry is in the file.  */
845       if (unlikely ((size_t) elf->state.ar.offset
846 		    > elf->start_offset + elf->maximum_size
847 		    || (elf->start_offset + elf->maximum_size
848 			- elf->state.ar.offset) < sizeof (struct ar_hdr)))
849 	{
850 	  /* This record is not anymore in the file.  */
851 	  __libelf_seterrno (ELF_E_RANGE);
852 	  return -1;
853 	}
854       ar_hdr = (struct ar_hdr *) (elf->map_address + elf->state.ar.offset);
855     }
856   else
857     {
858       ar_hdr = &elf->state.ar.ar_hdr;
859 
860       if (unlikely (pread_retry (elf->fildes, ar_hdr, sizeof (struct ar_hdr),
861 				 elf->state.ar.offset)
862 		    != sizeof (struct ar_hdr)))
863 	{
864 	  /* Something went wrong while reading the file.  */
865 	  __libelf_seterrno (ELF_E_RANGE);
866 	  return -1;
867 	}
868     }
869 
870   /* One little consistency check.  */
871   if (unlikely (memcmp (ar_hdr->ar_fmag, ARFMAG, 2) != 0))
872     {
873       /* This is no valid archive.  */
874       __libelf_seterrno (ELF_E_ARCHIVE_FMAG);
875       return -1;
876     }
877 
878   /* Copy the raw name over to a NUL terminated buffer.  */
879   *((char *) mempcpy (elf->state.ar.raw_name, ar_hdr->ar_name, 16)) = '\0';
880 
881   elf_ar_hdr = &elf->state.ar.elf_ar_hdr;
882 
883   /* Now convert the `struct ar_hdr' into `Elf_Arhdr'.
884      Determine whether this is a special entry.  */
885   if (ar_hdr->ar_name[0] == '/')
886     {
887       if (ar_hdr->ar_name[1] == ' '
888 	  && memcmp (ar_hdr->ar_name, "/               ", 16) == 0)
889 	/* This is the index.  */
890 	elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "/", 2);
891       else if (ar_hdr->ar_name[1] == 'S'
892 	       && memcmp (ar_hdr->ar_name, "/SYM64/         ", 16) == 0)
893 	/* 64-bit index.  */
894 	elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "/SYM64/", 8);
895       else if (ar_hdr->ar_name[1] == '/'
896 	       && memcmp (ar_hdr->ar_name, "//              ", 16) == 0)
897 	/* This is the array with the long names.  */
898 	elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "//", 3);
899       else if (likely  (isdigit (ar_hdr->ar_name[1])))
900 	{
901 	  size_t offset;
902 
903 	  /* This is a long name.  First we have to read the long name
904 	     table, if this hasn't happened already.  */
905 	  if (unlikely (elf->state.ar.long_names == NULL
906 			&& read_long_names (elf) == NULL))
907 	    {
908 	      /* No long name table although it is reference.  The archive is
909 		 broken.  */
910 	      __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
911 	      return -1;
912 	    }
913 
914 	  offset = atol (ar_hdr->ar_name + 1);
915 	  if (unlikely (offset >= elf->state.ar.long_names_len))
916 	    {
917 	      /* The index in the long name table is larger than the table.  */
918 	      __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
919 	      return -1;
920 	    }
921 	  elf_ar_hdr->ar_name = elf->state.ar.long_names + offset;
922 	}
923       else
924 	{
925 	  /* This is none of the known special entries.  */
926 	  __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
927 	  return -1;
928 	}
929     }
930   else
931     {
932       char *endp;
933 
934       /* It is a normal entry.  Copy over the name.  */
935       endp = (char *) memccpy (elf->state.ar.ar_name, ar_hdr->ar_name,
936 			       '/', 16);
937       if (endp != NULL)
938 	endp[-1] = '\0';
939       else
940 	{
941 	  /* In the old BSD style of archive, there is no / terminator.
942 	     Instead, there is space padding at the end of the name.  */
943 	  size_t i = 15;
944 	  do
945 	    elf->state.ar.ar_name[i] = '\0';
946 	  while (i > 0 && elf->state.ar.ar_name[--i] == ' ');
947 	}
948 
949       elf_ar_hdr->ar_name = elf->state.ar.ar_name;
950     }
951 
952   if (unlikely (ar_hdr->ar_size[0] == ' '))
953     /* Something is really wrong.  We cannot live without a size for
954        the member since it will not be possible to find the next
955        archive member.  */
956     {
957       __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
958       return -1;
959     }
960 
961   /* Since there are no specialized functions to convert ASCII to
962      time_t, uid_t, gid_t, mode_t, and off_t we use either atol or
963      atoll depending on the size of the types.  We are also prepared
964      for the case where the whole field in the `struct ar_hdr' is
965      filled in which case we cannot simply use atol/l but instead have
966      to create a temporary copy.  */
967 
968 #define INT_FIELD(FIELD)						      \
969   do									      \
970     {									      \
971       char buf[sizeof (ar_hdr->FIELD) + 1];				      \
972       const char *string = ar_hdr->FIELD;				      \
973       if (ar_hdr->FIELD[sizeof (ar_hdr->FIELD) - 1] != ' ')		      \
974 	{								      \
975 	  *((char *) mempcpy (buf, ar_hdr->FIELD, sizeof (ar_hdr->FIELD)))  \
976 	    = '\0';							      \
977 	  string = buf;							      \
978 	}								      \
979       if (sizeof (elf_ar_hdr->FIELD) <= sizeof (long int))		      \
980 	elf_ar_hdr->FIELD = (__typeof (elf_ar_hdr->FIELD)) atol (string);     \
981       else								      \
982 	elf_ar_hdr->FIELD = (__typeof (elf_ar_hdr->FIELD)) atoll (string);    \
983     }									      \
984   while (0)
985 
986   INT_FIELD (ar_date);
987   INT_FIELD (ar_uid);
988   INT_FIELD (ar_gid);
989   INT_FIELD (ar_mode);
990   INT_FIELD (ar_size);
991 
992   if (elf_ar_hdr->ar_size < 0)
993     {
994       __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
995       return -1;
996     }
997 
998   /* Truncated file?  */
999   size_t maxsize;
1000   maxsize = (elf->start_offset + elf->maximum_size
1001 	     - elf->state.ar.offset - sizeof (struct ar_hdr));
1002   if ((size_t) elf_ar_hdr->ar_size > maxsize)
1003     elf_ar_hdr->ar_size = maxsize;
1004 
1005   return 0;
1006 }
1007 
1008 
1009 /* We were asked to return a clone of an existing descriptor.  This
1010    function must be called with the lock on the parent descriptor
1011    being held. */
1012 static Elf *
dup_elf(int fildes,Elf_Cmd cmd,Elf * ref)1013 dup_elf (int fildes, Elf_Cmd cmd, Elf *ref)
1014 {
1015   struct Elf *result;
1016 
1017   if (fildes == -1)
1018     /* Allow the user to pass -1 as the file descriptor for the new file.  */
1019     fildes = ref->fildes;
1020   /* The file descriptor better should be the same.  If it was disconnected
1021      already (using `elf_cntl') we do not test it.  */
1022   else if (unlikely (ref->fildes != -1 && fildes != ref->fildes))
1023     {
1024       __libelf_seterrno (ELF_E_FD_MISMATCH);
1025       return NULL;
1026     }
1027 
1028   /* The mode must allow reading.  I.e., a descriptor creating with a
1029      command different then ELF_C_READ, ELF_C_WRITE and ELF_C_RDWR is
1030      not allowed.  */
1031   if (unlikely (ref->cmd != ELF_C_READ && ref->cmd != ELF_C_READ_MMAP
1032 		&& ref->cmd != ELF_C_WRITE && ref->cmd != ELF_C_WRITE_MMAP
1033 		&& ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP
1034 		&& ref->cmd != ELF_C_READ_MMAP_PRIVATE))
1035     {
1036       __libelf_seterrno (ELF_E_INVALID_OP);
1037       return NULL;
1038     }
1039 
1040   /* Now it is time to distinguish between reading normal files and
1041      archives.  Normal files can easily be handled be incrementing the
1042      reference counter and return the same descriptor.  */
1043   if (ref->kind != ELF_K_AR)
1044     {
1045       ++ref->ref_count;
1046       return ref;
1047     }
1048 
1049   /* This is an archive.  We must create a descriptor for the archive
1050      member the internal pointer of the archive file descriptor is
1051      pointing to.  First read the header of the next member if this
1052      has not happened already.  */
1053   if (ref->state.ar.elf_ar_hdr.ar_name == NULL
1054       && __libelf_next_arhdr_wrlock (ref) != 0)
1055     /* Something went wrong.  Maybe there is no member left.  */
1056     return NULL;
1057 
1058   /* We have all the information we need about the next archive member.
1059      Now create a descriptor for it.  */
1060   result = read_file (fildes, ref->state.ar.offset + sizeof (struct ar_hdr),
1061 		      ref->state.ar.elf_ar_hdr.ar_size, cmd, ref);
1062 
1063   /* Enlist this new descriptor in the list of children.  */
1064   if (result != NULL)
1065     {
1066       result->next = ref->state.ar.children;
1067       ref->state.ar.children = result;
1068     }
1069 
1070   return result;
1071 }
1072 
1073 
1074 /* Return descriptor for empty file ready for writing.  */
1075 static struct Elf *
write_file(int fd,Elf_Cmd cmd)1076 write_file (int fd, Elf_Cmd cmd)
1077 {
1078   /* We simply create an empty `Elf' structure.  */
1079 #define NSCNSALLOC	10
1080   Elf *result = allocate_elf (fd, NULL, 0, 0, cmd, NULL, ELF_K_ELF,
1081 			      NSCNSALLOC * sizeof (Elf_Scn));
1082 
1083   if (result != NULL)
1084     {
1085       /* We have to write to the file in any case.  */
1086       result->flags = ELF_F_DIRTY;
1087 
1088       /* Some more or less arbitrary value.  */
1089       result->state.elf.scnincr = NSCNSALLOC;
1090 
1091       /* We have allocated room for some sections.  */
1092       assert (offsetof (struct Elf, state.elf32.scns)
1093 	      == offsetof (struct Elf, state.elf64.scns));
1094       result->state.elf.scns_last = &result->state.elf32.scns;
1095       result->state.elf32.scns.max = NSCNSALLOC;
1096     }
1097 
1098   return result;
1099 }
1100 
1101 /* Lock if necessary before dup an archive.  */
1102 static inline Elf *
lock_dup_elf(int fildes,Elf_Cmd cmd,Elf * ref)1103 lock_dup_elf (int fildes, Elf_Cmd cmd, Elf *ref)
1104 {
1105   /* We need wrlock to dup an archive.  */
1106   if (ref->kind == ELF_K_AR)
1107     {
1108       rwlock_unlock (ref->lock);
1109       rwlock_wrlock (ref->lock);
1110     }
1111     /* Duplicate the descriptor.  */
1112   return dup_elf (fildes, cmd, ref);
1113 }
1114 
1115 /* Return a descriptor for the file belonging to FILDES.  */
1116 Elf *
elf_begin(int fildes,Elf_Cmd cmd,Elf * ref)1117 elf_begin (int fildes, Elf_Cmd cmd, Elf *ref)
1118 {
1119   Elf *retval;
1120 
1121   if (unlikely (__libelf_version != EV_CURRENT))
1122     {
1123       /* Version wasn't set so far.  */
1124       __libelf_seterrno (ELF_E_NO_VERSION);
1125       return NULL;
1126     }
1127 
1128   if (ref != NULL)
1129     /* Make sure the descriptor is not suddenly going away.  */
1130     rwlock_rdlock (ref->lock);
1131   else if (unlikely (fcntl (fildes, F_GETFD) == -1 && errno == EBADF))
1132     {
1133       /* We cannot do anything productive without a file descriptor.  */
1134       __libelf_seterrno (ELF_E_INVALID_FILE);
1135       return NULL;
1136     }
1137 
1138   switch (cmd)
1139     {
1140     case ELF_C_NULL:
1141       /* We simply return a NULL pointer.  */
1142       retval = NULL;
1143       break;
1144 
1145     case ELF_C_READ_MMAP_PRIVATE:
1146       /* If we have a reference it must also be opened this way.  */
1147       if (unlikely (ref != NULL && ref->cmd != ELF_C_READ_MMAP_PRIVATE))
1148 	{
1149 	  __libelf_seterrno (ELF_E_INVALID_CMD);
1150 	  retval = NULL;
1151 	  break;
1152 	}
1153       FALLTHROUGH;
1154 
1155     case ELF_C_READ:
1156     case ELF_C_READ_MMAP:
1157       if (ref != NULL)
1158 	retval = lock_dup_elf (fildes, cmd, ref);
1159       else
1160 	/* Create descriptor for existing file.  */
1161 	retval = read_file (fildes, 0, ~((size_t) 0), cmd, NULL);
1162       break;
1163 
1164     case ELF_C_RDWR:
1165     case ELF_C_RDWR_MMAP:
1166       /* If we have a REF object it must also be opened using this
1167 	 command.  */
1168       if (ref != NULL)
1169 	{
1170 	  if (unlikely (ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP
1171 			&& ref->cmd != ELF_C_WRITE
1172 			&& ref->cmd != ELF_C_WRITE_MMAP))
1173 	    {
1174 	      /* This is not ok.  REF must also be opened for writing.  */
1175 	      __libelf_seterrno (ELF_E_INVALID_CMD);
1176 	      retval = NULL;
1177 	    }
1178 	  else
1179 	    retval = lock_dup_elf (fildes, cmd, ref);
1180 	}
1181       else
1182 	/* Create descriptor for existing file.  */
1183 	retval = read_file (fildes, 0, ~((size_t) 0), cmd, NULL);
1184       break;
1185 
1186     case ELF_C_WRITE:
1187     case ELF_C_WRITE_MMAP:
1188       /* We ignore REF and prepare a descriptor to write a new file.  */
1189       retval = write_file (fildes, cmd);
1190       break;
1191 
1192     default:
1193       __libelf_seterrno (ELF_E_INVALID_CMD);
1194       retval = NULL;
1195       break;
1196     }
1197 
1198   /* Release the lock.  */
1199   if (ref != NULL)
1200     rwlock_unlock (ref->lock);
1201 
1202   return retval;
1203 }
1204 INTDEF(elf_begin)
1205