xref: /third_party/elfutils/libelf/elf_readall.c (revision da0c48c4)
1da0c48c4Sopenharmony_ci/* Read all of the file associated with the descriptor.
2da0c48c4Sopenharmony_ci   Copyright (C) 1998-2009, 2015 Red Hat, Inc.
3da0c48c4Sopenharmony_ci   This file is part of elfutils.
4da0c48c4Sopenharmony_ci   Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
5da0c48c4Sopenharmony_ci
6da0c48c4Sopenharmony_ci   This file is free software; you can redistribute it and/or modify
7da0c48c4Sopenharmony_ci   it under the terms of either
8da0c48c4Sopenharmony_ci
9da0c48c4Sopenharmony_ci     * the GNU Lesser General Public License as published by the Free
10da0c48c4Sopenharmony_ci       Software Foundation; either version 3 of the License, or (at
11da0c48c4Sopenharmony_ci       your option) any later version
12da0c48c4Sopenharmony_ci
13da0c48c4Sopenharmony_ci   or
14da0c48c4Sopenharmony_ci
15da0c48c4Sopenharmony_ci     * the GNU General Public License as published by the Free
16da0c48c4Sopenharmony_ci       Software Foundation; either version 2 of the License, or (at
17da0c48c4Sopenharmony_ci       your option) any later version
18da0c48c4Sopenharmony_ci
19da0c48c4Sopenharmony_ci   or both in parallel, as here.
20da0c48c4Sopenharmony_ci
21da0c48c4Sopenharmony_ci   elfutils is distributed in the hope that it will be useful, but
22da0c48c4Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
23da0c48c4Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24da0c48c4Sopenharmony_ci   General Public License for more details.
25da0c48c4Sopenharmony_ci
26da0c48c4Sopenharmony_ci   You should have received copies of the GNU General Public License and
27da0c48c4Sopenharmony_ci   the GNU Lesser General Public License along with this program.  If
28da0c48c4Sopenharmony_ci   not, see <http://www.gnu.org/licenses/>.  */
29da0c48c4Sopenharmony_ci
30da0c48c4Sopenharmony_ci#ifdef HAVE_CONFIG_H
31da0c48c4Sopenharmony_ci# include <config.h>
32da0c48c4Sopenharmony_ci#endif
33da0c48c4Sopenharmony_ci
34da0c48c4Sopenharmony_ci#include <errno.h>
35da0c48c4Sopenharmony_ci#include <sys/stat.h>
36da0c48c4Sopenharmony_ci
37da0c48c4Sopenharmony_ci#include "libelfP.h"
38da0c48c4Sopenharmony_ci#include "common.h"
39da0c48c4Sopenharmony_ci
40da0c48c4Sopenharmony_ci
41da0c48c4Sopenharmony_cistatic void
42da0c48c4Sopenharmony_ciset_address (Elf *elf, size_t offset)
43da0c48c4Sopenharmony_ci{
44da0c48c4Sopenharmony_ci  if (elf->kind == ELF_K_AR)
45da0c48c4Sopenharmony_ci    {
46da0c48c4Sopenharmony_ci      Elf *child = elf->state.ar.children;
47da0c48c4Sopenharmony_ci
48da0c48c4Sopenharmony_ci      while (child != NULL)
49da0c48c4Sopenharmony_ci	{
50da0c48c4Sopenharmony_ci	  if (child->map_address == NULL)
51da0c48c4Sopenharmony_ci	    {
52da0c48c4Sopenharmony_ci	      child->map_address = elf->map_address;
53da0c48c4Sopenharmony_ci	      child->start_offset -= offset;
54da0c48c4Sopenharmony_ci	      if (child->kind == ELF_K_AR)
55da0c48c4Sopenharmony_ci		child->state.ar.offset -= offset;
56da0c48c4Sopenharmony_ci
57da0c48c4Sopenharmony_ci	      set_address (child, offset);
58da0c48c4Sopenharmony_ci	    }
59da0c48c4Sopenharmony_ci
60da0c48c4Sopenharmony_ci	  child = child->next;
61da0c48c4Sopenharmony_ci	}
62da0c48c4Sopenharmony_ci    }
63da0c48c4Sopenharmony_ci}
64da0c48c4Sopenharmony_ci
65da0c48c4Sopenharmony_ci
66da0c48c4Sopenharmony_cichar *
67da0c48c4Sopenharmony_ciinternal_function
68da0c48c4Sopenharmony_ci__libelf_readall (Elf *elf)
69da0c48c4Sopenharmony_ci{
70da0c48c4Sopenharmony_ci  /* Get the file.  */
71da0c48c4Sopenharmony_ci  rwlock_wrlock (elf->lock);
72da0c48c4Sopenharmony_ci
73da0c48c4Sopenharmony_ci  if (elf->map_address == NULL && unlikely (elf->fildes == -1))
74da0c48c4Sopenharmony_ci    {
75da0c48c4Sopenharmony_ci      __libelf_seterrno (ELF_E_INVALID_HANDLE);
76da0c48c4Sopenharmony_ci      rwlock_unlock (elf->lock);
77da0c48c4Sopenharmony_ci      return NULL;
78da0c48c4Sopenharmony_ci    }
79da0c48c4Sopenharmony_ci
80da0c48c4Sopenharmony_ci  /* If the file is not mmap'ed and not previously loaded, do it now.  */
81da0c48c4Sopenharmony_ci  if (elf->map_address == NULL)
82da0c48c4Sopenharmony_ci    {
83da0c48c4Sopenharmony_ci      char *mem = NULL;
84da0c48c4Sopenharmony_ci
85da0c48c4Sopenharmony_ci      /* If this is an archive and we have derived descriptors get the
86da0c48c4Sopenharmony_ci	 locks for all of them.  */
87da0c48c4Sopenharmony_ci      libelf_acquire_all (elf);
88da0c48c4Sopenharmony_ci
89da0c48c4Sopenharmony_ci      if (elf->maximum_size == ~((size_t) 0))
90da0c48c4Sopenharmony_ci	{
91da0c48c4Sopenharmony_ci	  /* We don't yet know how large the file is.   Determine that now.  */
92da0c48c4Sopenharmony_ci	  struct stat st;
93da0c48c4Sopenharmony_ci
94da0c48c4Sopenharmony_ci	  if (fstat (elf->fildes, &st) < 0)
95da0c48c4Sopenharmony_ci	    goto read_error;
96da0c48c4Sopenharmony_ci
97da0c48c4Sopenharmony_ci	  if (sizeof (size_t) >= sizeof (st.st_size)
98da0c48c4Sopenharmony_ci	      || st.st_size <= ~((size_t) 0))
99da0c48c4Sopenharmony_ci	    elf->maximum_size = (size_t) st.st_size;
100da0c48c4Sopenharmony_ci	  else
101da0c48c4Sopenharmony_ci	    {
102da0c48c4Sopenharmony_ci	      errno = EOVERFLOW;
103da0c48c4Sopenharmony_ci	      goto read_error;
104da0c48c4Sopenharmony_ci	    }
105da0c48c4Sopenharmony_ci	}
106da0c48c4Sopenharmony_ci
107da0c48c4Sopenharmony_ci      /* Allocate all the memory we need.  */
108da0c48c4Sopenharmony_ci      mem = malloc (elf->maximum_size);
109da0c48c4Sopenharmony_ci      if (mem != NULL)
110da0c48c4Sopenharmony_ci	{
111da0c48c4Sopenharmony_ci	  /* Read the file content.  */
112da0c48c4Sopenharmony_ci	  if (unlikely ((size_t) pread_retry (elf->fildes, mem,
113da0c48c4Sopenharmony_ci					      elf->maximum_size,
114da0c48c4Sopenharmony_ci					      elf->start_offset)
115da0c48c4Sopenharmony_ci			!= elf->maximum_size))
116da0c48c4Sopenharmony_ci	    {
117da0c48c4Sopenharmony_ci	      /* Something went wrong.  */
118da0c48c4Sopenharmony_ci	    read_error:
119da0c48c4Sopenharmony_ci	      __libelf_seterrno (ELF_E_READ_ERROR);
120da0c48c4Sopenharmony_ci	      free (mem);
121da0c48c4Sopenharmony_ci	    }
122da0c48c4Sopenharmony_ci	  else
123da0c48c4Sopenharmony_ci	    {
124da0c48c4Sopenharmony_ci	      /* Remember the address.  */
125da0c48c4Sopenharmony_ci	      elf->map_address = mem;
126da0c48c4Sopenharmony_ci
127da0c48c4Sopenharmony_ci	      /* Also remember that we allocated the memory.  */
128da0c48c4Sopenharmony_ci	      elf->flags |= ELF_F_MALLOCED;
129da0c48c4Sopenharmony_ci
130da0c48c4Sopenharmony_ci	      /* Propagate the information down to all children and
131da0c48c4Sopenharmony_ci		 their children.  */
132da0c48c4Sopenharmony_ci	      set_address (elf, elf->start_offset);
133da0c48c4Sopenharmony_ci
134da0c48c4Sopenharmony_ci	      /* Correct the own offsets.  */
135da0c48c4Sopenharmony_ci	      if (elf->kind == ELF_K_AR)
136da0c48c4Sopenharmony_ci		elf->state.ar.offset -= elf->start_offset;
137da0c48c4Sopenharmony_ci	      elf->start_offset = 0;
138da0c48c4Sopenharmony_ci	    }
139da0c48c4Sopenharmony_ci	}
140da0c48c4Sopenharmony_ci      else
141da0c48c4Sopenharmony_ci	__libelf_seterrno (ELF_E_NOMEM);
142da0c48c4Sopenharmony_ci
143da0c48c4Sopenharmony_ci      /* Free the locks on the children.  */
144da0c48c4Sopenharmony_ci      libelf_release_all (elf);
145da0c48c4Sopenharmony_ci    }
146da0c48c4Sopenharmony_ci
147da0c48c4Sopenharmony_ci  rwlock_unlock (elf->lock);
148da0c48c4Sopenharmony_ci
149da0c48c4Sopenharmony_ci  return (char *) elf->map_address;
150da0c48c4Sopenharmony_ci}
151