• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Functions to handle creation of Linux archives.
2    Copyright (C) 2007-2012 Red Hat, Inc.
3    This file is part of elfutils.
4    Written by Ulrich Drepper <drepper@redhat.com>, 2007.
5 
6    This file is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10 
11    elfutils is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18 
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22 
23 #include <assert.h>
24 #include <error.h>
25 #include <gelf.h>
26 #include <libintl.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <time.h>
30 
31 #include <system.h>
32 
33 #include "arlib.h"
34 
35 
36 /* The one symbol table we hanble.  */
37 struct arlib_symtab symtab;
38 
39 
40 /* Initialize ARLIB_SYMTAB structure.  */
41 void
arlib_init(void)42 arlib_init (void)
43 {
44 #define obstack_chunk_alloc xmalloc
45 #define obstack_chunk_free free
46   obstack_init (&symtab.symsoffob);
47   obstack_init (&symtab.symsnameob);
48   obstack_init (&symtab.longnamesob);
49 
50   /* We add the archive header here as well, that avoids allocating
51      another memory block.  */
52   struct ar_hdr ar_hdr;
53   memcpy (ar_hdr.ar_name, "/               ", sizeof (ar_hdr.ar_name));
54   /* Using snprintf here has a problem: the call always wants to add a
55      NUL byte.  We could use a trick whereby we specify the target
56      buffer size longer than it is and this would not actually fail,
57      since all the fields are consecutive and we fill them in
58      sequence (i.e., the NUL byte gets overwritten).  But
59      _FORTIFY_SOURCE=2 would not let us play these games.  Therefore
60      we play it safe.  */
61   char tmpbuf[sizeof (ar_hdr.ar_date) + 1];
62   int s = snprintf (tmpbuf, sizeof (tmpbuf), "%-*lld",
63 		    (int) sizeof (ar_hdr.ar_date),
64                     (arlib_deterministic_output ? 0
65                      : (long long int) time (NULL)));
66   memcpy (ar_hdr.ar_date, tmpbuf, s);
67   assert ((sizeof (struct ar_hdr)  % sizeof (uint32_t)) == 0);
68 
69   /* Note the string for the ar_uid and ar_gid cases is longer than
70      necessary.  This does not matter since we copy only as much as
71      necessary but it helps the compiler to use the same string for
72      the ar_mode case.  */
73   memcpy (ar_hdr.ar_uid, "0       ", sizeof (ar_hdr.ar_uid));
74   memcpy (ar_hdr.ar_gid, "0       ", sizeof (ar_hdr.ar_gid));
75   memcpy (ar_hdr.ar_mode, "0       ", sizeof (ar_hdr.ar_mode));
76   memcpy (ar_hdr.ar_fmag, ARFMAG, sizeof (ar_hdr.ar_fmag));
77 
78   /* Add the archive header to the file content.  */
79   obstack_grow (&symtab.symsoffob, &ar_hdr, sizeof (ar_hdr));
80 
81   /* The first word in the offset table specifies the size.  Create
82      such an entry now.  The real value will be filled-in later.  For
83      all supported platforms the following is true.  */
84   assert (sizeof (uint32_t) == sizeof (int));
85   obstack_int_grow (&symtab.symsoffob, 0);
86 
87   /* The long name obstack also gets its archive header.  As above,
88      some of the input strings are longer than required but we only
89      copy the necessary part.  */
90   memcpy (ar_hdr.ar_name, "//              ", sizeof (ar_hdr.ar_name));
91   memcpy (ar_hdr.ar_date, "            ", sizeof (ar_hdr.ar_date));
92   memcpy (ar_hdr.ar_uid, "            ", sizeof (ar_hdr.ar_uid));
93   memcpy (ar_hdr.ar_gid, "            ", sizeof (ar_hdr.ar_gid));
94   memcpy (ar_hdr.ar_mode, "            ", sizeof (ar_hdr.ar_mode));
95   /* The ar_size field will be filled in later and ar_fmag is already OK.  */
96   obstack_grow (&symtab.longnamesob, &ar_hdr, sizeof (ar_hdr));
97 
98   /* All other members are zero.  */
99   symtab.symsofflen = 0;
100   symtab.symsoff = NULL;
101   symtab.symsnamelen = 0;
102   symtab.symsname = NULL;
103 }
104 
105 
106 /* Finalize ARLIB_SYMTAB content.  */
107 void
arlib_finalize(void)108 arlib_finalize (void)
109 {
110   char tmpbuf[sizeof (((struct ar_hdr *) NULL)->ar_size) + 1];
111 
112   symtab.longnameslen = obstack_object_size (&symtab.longnamesob);
113   if (symtab.longnameslen != sizeof (struct ar_hdr))
114     {
115       if ((symtab.longnameslen & 1) != 0)
116 	{
117 	  /* Add one more byte to make length even.  */
118 	  obstack_grow (&symtab.longnamesob, "\n", 1);
119 	  ++symtab.longnameslen;
120 	}
121 
122       symtab.longnames = obstack_finish (&symtab.longnamesob);
123 
124       int s = snprintf (tmpbuf, sizeof (tmpbuf), "%-*zu",
125 			(int) sizeof (((struct ar_hdr *) NULL)->ar_size),
126 			symtab.longnameslen - sizeof (struct ar_hdr));
127       memcpy (&((struct ar_hdr *) symtab.longnames)->ar_size, tmpbuf, s);
128     }
129 
130   symtab.symsofflen = obstack_object_size (&symtab.symsoffob);
131   assert (symtab.symsofflen % sizeof (uint32_t) == 0);
132   if (symtab.symsofflen != 0)
133     {
134       symtab.symsoff = (uint32_t *) obstack_finish (&symtab.symsoffob);
135 
136       /* Fill in the number of offsets now.  */
137       symtab.symsoff[AR_HDR_WORDS] = le_bswap_32 ((symtab.symsofflen
138 						    - sizeof (struct ar_hdr))
139 						   / sizeof (uint32_t) - 1);
140     }
141 
142   symtab.symsnamelen = obstack_object_size (&symtab.symsnameob);
143   if ((symtab.symsnamelen & 1) != 0)
144     {
145       /* Add one more NUL byte to make length even.  */
146       obstack_grow (&symtab.symsnameob, "", 1);
147       ++symtab.symsnamelen;
148     }
149   symtab.symsname = obstack_finish (&symtab.symsnameob);
150 
151   /* Determine correction for the offsets in the symbol table.   */
152   off_t disp = 0;
153   if (symtab.symsnamelen > 0)
154     disp = symtab.symsofflen + symtab.symsnamelen;
155   if (symtab.longnameslen > sizeof (struct ar_hdr))
156     disp += symtab.longnameslen;
157 
158   if (disp != 0 && symtab.symsoff != NULL)
159     {
160       uint32_t nsyms = le_bswap_32 (symtab.symsoff[AR_HDR_WORDS]);
161 
162       for (uint32_t cnt = 1; cnt <= nsyms; ++cnt)
163 	{
164 	  uint32_t val = le_bswap_32 (symtab.symsoff[AR_HDR_WORDS + cnt]);
165 	  val += disp;
166 	  symtab.symsoff[AR_HDR_WORDS + cnt] = le_bswap_32 (val);
167 	}
168     }
169 
170   /* See comment for ar_date above.  */
171   memcpy (&((struct ar_hdr *) symtab.symsoff)->ar_size, tmpbuf,
172 	  snprintf (tmpbuf, sizeof (tmpbuf), "%-*zu",
173 		    (int) sizeof (((struct ar_hdr *) NULL)->ar_size),
174 		    symtab.symsofflen + symtab.symsnamelen
175 		    - sizeof (struct ar_hdr)));
176 }
177 
178 
179 /* Free resources for ARLIB_SYMTAB.  */
180 void
arlib_fini(void)181 arlib_fini (void)
182 {
183   obstack_free (&symtab.symsoffob, NULL);
184   obstack_free (&symtab.symsnameob, NULL);
185   obstack_free (&symtab.longnamesob, NULL);
186 }
187 
188 
189 /* Add name a file offset of a symbol.  */
190 void
arlib_add_symref(const char * symname,off_t symoff)191 arlib_add_symref (const char *symname, off_t symoff)
192 {
193   /* For all supported platforms the following is true.  */
194   assert (sizeof (uint32_t) == sizeof (int));
195   obstack_int_grow (&symtab.symsoffob, (int) le_bswap_32 (symoff));
196 
197   size_t symname_len = strlen (symname) + 1;
198   obstack_grow (&symtab.symsnameob, symname, symname_len);
199 }
200 
201 
202 /* Add symbols from ELF with value OFFSET to the symbol table SYMTAB.  */
203 void
arlib_add_symbols(Elf * elf,const char * arfname,const char * membername,off_t off)204 arlib_add_symbols (Elf *elf, const char *arfname, const char *membername,
205 		   off_t off)
206 {
207   if (sizeof (off) > sizeof (uint32_t) && off > ~((uint32_t) 0))
208     /* The archive is too big.  */
209     error (EXIT_FAILURE, 0, gettext ("the archive '%s' is too large"),
210 	   arfname);
211 
212   /* We only add symbol tables for ELF files.  It makes not much sense
213      to add symbols from executables but we do so for compatibility.
214      For DSOs and executables we use the dynamic symbol table, for
215      relocatable files all the DT_SYMTAB tables.  */
216   if (elf_kind (elf) != ELF_K_ELF)
217     return;
218 
219   GElf_Ehdr ehdr_mem;
220   GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
221   if (ehdr == NULL)
222     error (EXIT_FAILURE, 0, gettext ("cannot read ELF header of %s(%s): %s"),
223 	   arfname, membername, elf_errmsg (-1));
224 
225   GElf_Word symtype;
226   if (ehdr->e_type == ET_REL)
227     symtype = SHT_SYMTAB;
228   else if (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN)
229     symtype = SHT_DYNSYM;
230   else
231     /* We do not handle that type.  */
232     return;
233 
234   /* Iterate over all sections.  */
235   Elf_Scn *scn = NULL;
236   while ((scn = elf_nextscn (elf, scn)) != NULL)
237     {
238       /* Get the section header.  */
239       GElf_Shdr shdr_mem;
240       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
241       if (shdr == NULL)
242 	continue;
243 
244       if (shdr->sh_type != symtype)
245 	continue;
246 
247       Elf_Data *data = elf_getdata (scn, NULL);
248       if (data == NULL)
249 	continue;
250 
251       int nsyms = shdr->sh_size / shdr->sh_entsize;
252       for (int ndx = shdr->sh_info; ndx < nsyms; ++ndx)
253 	{
254 	  GElf_Sym sym_mem;
255 	  GElf_Sym *sym = gelf_getsym (data, ndx, &sym_mem);
256 	  if (sym == NULL)
257 	    continue;
258 
259 	  /* Ignore undefined symbols.  */
260 	  if (sym->st_shndx == SHN_UNDEF)
261 	    continue;
262 
263 	  /* Use this symbol.  */
264 	  const char *symname = elf_strptr (elf, shdr->sh_link, sym->st_name);
265 	  if (symname != NULL)
266 	    arlib_add_symref (symname, off);
267 	}
268 
269       /* Only relocatable files can have more than one symbol table.  */
270       if (ehdr->e_type != ET_REL)
271 	break;
272     }
273 }
274