125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Functions to handle creation of Linux archives.
225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Copyright (C) 2007-2012 Red Hat, Inc.
325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Written by Ulrich Drepper <drepper@redhat.com>, 2007.
425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is free software; you can redistribute it and/or modify
625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   it under the terms of the GNU General Public License as published by the
725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Free Software Foundation; version 2 of the License.
825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
925b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is distributed in the hope that it will be useful, but
1025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   WITHOUT ANY WARRANTY; without even the implied warranty of
1125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   General Public License for more details.
1325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   You should have received a copy of the GNU General Public License along
1525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   with Red Hat elfutils; if not, write to the Free Software Foundation,
1625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
1725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1825b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is an included package of the Open Invention Network.
1925b3c049e70834cf33790a28643ab058b507b35cBen Cheng   An included package of the Open Invention Network is a package for which
2025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Open Invention Network licensees cross-license their patents.  No patent
2125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   license is granted, either expressly or impliedly, by designation as an
2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   included package.  Should you wish to participate in the Open Invention
2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Network licensing program, please visit www.openinventionnetwork.com
2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   <http://www.openinventionnetwork.com>.  */
2525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
2625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef HAVE_CONFIG_H
2725b3c049e70834cf33790a28643ab058b507b35cBen Cheng# include <config.h>
2825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <assert.h>
3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <error.h>
3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <gelf.h>
3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <libintl.h>
3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdio.h>
3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdlib.h>
3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <time.h>
3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <system.h>
3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "arlib.h"
4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* The one symbol table we hanble.  */
4425b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct arlib_symtab symtab;
4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Initialize ARLIB_SYMTAB structure.  */
4825b3c049e70834cf33790a28643ab058b507b35cBen Chengvoid
4925b3c049e70834cf33790a28643ab058b507b35cBen Chengarlib_init (void)
5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define obstack_chunk_alloc xmalloc
5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define obstack_chunk_free free
5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  obstack_init (&symtab.symsoffob);
5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  obstack_init (&symtab.symsnameob);
5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  obstack_init (&symtab.longnamesob);
5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We add the archive header here as well, that avoids allocating
5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng     another memory block.  */
5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct ar_hdr ar_hdr;
6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  memcpy (ar_hdr.ar_name, "/               ", sizeof (ar_hdr.ar_name));
6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Using snprintf here has a problem: the call always wants to add a
6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng     NUL byte.  We could use a trick whereby we specify the target
6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng     buffer size longer than it is and this would not actually fail,
6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng     since all the fields are consecutive and we fill them in
6525b3c049e70834cf33790a28643ab058b507b35cBen Cheng     sequence (i.e., the NUL byte gets overwritten).  But
6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng     _FORTIFY_SOURCE=2 would not let us play these games.  Therefore
6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng     we play it safe.  */
6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char tmpbuf[sizeof (ar_hdr.ar_date) + 1];
6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  memcpy (ar_hdr.ar_date, tmpbuf,
7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  snprintf (tmpbuf, sizeof (tmpbuf), "%-*lld",
7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    (int) sizeof (ar_hdr.ar_date),
7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng                    (arlib_deterministic_output ? 0
7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng                     : (long long int) time (NULL))));
7425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert ((sizeof (struct ar_hdr)  % sizeof (uint32_t)) == 0);
7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Note the string for the ar_uid and ar_gid cases is longer than
7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng     necessary.  This does not matter since we copy only as much as
7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng     necessary but it helps the compiler to use the same string for
7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng     the ar_mode case.  */
8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  memcpy (ar_hdr.ar_uid, "0       ", sizeof (ar_hdr.ar_uid));
8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  memcpy (ar_hdr.ar_gid, "0       ", sizeof (ar_hdr.ar_gid));
8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  memcpy (ar_hdr.ar_mode, "0       ", sizeof (ar_hdr.ar_mode));
8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  memcpy (ar_hdr.ar_fmag, ARFMAG, sizeof (ar_hdr.ar_fmag));
8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Add the archive header to the file content.  */
8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  obstack_grow (&symtab.symsoffob, &ar_hdr, sizeof (ar_hdr));
8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* The first word in the offset table specifies the size.  Create
8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng     such an entry now.  The real value will be filled-in later.  For
9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng     all supported platforms the following is true.  */
9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (sizeof (uint32_t) == sizeof (int));
9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  obstack_int_grow (&symtab.symsoffob, 0);
9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* The long name obstack also gets its archive header.  As above,
9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng     some of the input strings are longer than required but we only
9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng     copy the necessary part.  */
9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  memcpy (ar_hdr.ar_name, "//              ", sizeof (ar_hdr.ar_name));
9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  memcpy (ar_hdr.ar_date, "            ", sizeof (ar_hdr.ar_date));
9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  memcpy (ar_hdr.ar_uid, "            ", sizeof (ar_hdr.ar_uid));
10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  memcpy (ar_hdr.ar_gid, "            ", sizeof (ar_hdr.ar_gid));
10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  memcpy (ar_hdr.ar_mode, "            ", sizeof (ar_hdr.ar_mode));
10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* The ar_size field will be filled in later and ar_fmag is already OK.  */
10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  obstack_grow (&symtab.longnamesob, &ar_hdr, sizeof (ar_hdr));
10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* All other members are zero.  */
10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  symtab.symsofflen = 0;
10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  symtab.symsoff = NULL;
10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  symtab.symsnamelen = 0;
10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  symtab.symsname = NULL;
11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
11325b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Finalize ARLIB_SYMTAB content.  */
11425b3c049e70834cf33790a28643ab058b507b35cBen Chengvoid
11525b3c049e70834cf33790a28643ab058b507b35cBen Chengarlib_finalize (void)
11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char tmpbuf[sizeof (((struct ar_hdr *) NULL)->ar_size) + 1];
11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  symtab.longnameslen = obstack_object_size (&symtab.longnamesob);
12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (symtab.longnameslen != sizeof (struct ar_hdr))
12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if ((symtab.longnameslen & 1) != 0)
12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Add one more byte to make length even.  */
12525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  obstack_grow (&symtab.longnamesob, "\n", 1);
12625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ++symtab.longnameslen;
12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      symtab.longnames = obstack_finish (&symtab.longnamesob);
13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      memcpy (&((struct ar_hdr *) symtab.longnames)->ar_size, tmpbuf,
13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      snprintf (tmpbuf, sizeof (tmpbuf), "%-*zu",
13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			(int) sizeof (((struct ar_hdr *) NULL)->ar_size),
13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			symtab.longnameslen - sizeof (struct ar_hdr)));
13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  symtab.symsofflen = obstack_object_size (&symtab.symsoffob);
13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (symtab.symsofflen % sizeof (uint32_t) == 0);
13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (symtab.symsofflen != 0)
14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      symtab.symsoff = (uint32_t *) obstack_finish (&symtab.symsoffob);
14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Fill in the number of offsets now.  */
14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      symtab.symsoff[AR_HDR_WORDS] = le_bswap_32 ((symtab.symsofflen
14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng						    - sizeof (struct ar_hdr))
14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng						   / sizeof (uint32_t) - 1);
14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  symtab.symsnamelen = obstack_object_size (&symtab.symsnameob);
15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((symtab.symsnamelen & 1) != 0)
15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Add one more NUL byte to make length even.  */
15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      obstack_grow (&symtab.symsnameob, "", 1);
15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ++symtab.symsnamelen;
15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  symtab.symsname = obstack_finish (&symtab.symsnameob);
15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Determine correction for the offsets in the symbol table.   */
15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  off_t disp = 0;
16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (symtab.symsnamelen > 0)
16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    disp = symtab.symsofflen + symtab.symsnamelen;
16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (symtab.longnameslen > sizeof (struct ar_hdr))
16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    disp += symtab.longnameslen;
16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (disp != 0 && symtab.symsoff != NULL)
16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint32_t nsyms = le_bswap_32 (symtab.symsoff[AR_HDR_WORDS]);
16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (uint32_t cnt = 1; cnt <= nsyms; ++cnt)
17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  uint32_t val = le_bswap_32 (symtab.symsoff[AR_HDR_WORDS + cnt]);
17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  val += disp;
17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  symtab.symsoff[AR_HDR_WORDS + cnt] = le_bswap_32 (val);
17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* See comment for ar_date above.  */
17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  memcpy (&((struct ar_hdr *) symtab.symsoff)->ar_size, tmpbuf,
17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  snprintf (tmpbuf, sizeof (tmpbuf), "%-*zu",
18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    (int) sizeof (((struct ar_hdr *) NULL)->ar_size),
18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    symtab.symsofflen + symtab.symsnamelen
18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    - sizeof (struct ar_hdr)));
18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Free resources for ARLIB_SYMTAB.  */
18725b3c049e70834cf33790a28643ab058b507b35cBen Chengvoid
18825b3c049e70834cf33790a28643ab058b507b35cBen Chengarlib_fini (void)
18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  obstack_free (&symtab.symsoffob, NULL);
19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  obstack_free (&symtab.symsnameob, NULL);
19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  obstack_free (&symtab.longnamesob, NULL);
19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Add name a file offset of a symbol.  */
19725b3c049e70834cf33790a28643ab058b507b35cBen Chengvoid
19825b3c049e70834cf33790a28643ab058b507b35cBen Chengarlib_add_symref (const char *symname, off_t symoff)
19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* For all supported platforms the following is true.  */
20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (sizeof (uint32_t) == sizeof (int));
20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  obstack_int_grow (&symtab.symsoffob, (int) le_bswap_32 (symoff));
20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t symname_len = strlen (symname) + 1;
20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  obstack_grow (&symtab.symsnameob, symname, symname_len);
20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Add symbols from ELF with value OFFSET to the symbol table SYMTAB.  */
21025b3c049e70834cf33790a28643ab058b507b35cBen Chengvoid
21125b3c049e70834cf33790a28643ab058b507b35cBen Chengarlib_add_symbols (Elf *elf, const char *arfname, const char *membername,
21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   off_t off)
21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (sizeof (off) > sizeof (uint32_t) && off > ~((uint32_t) 0))
21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* The archive is too big.  */
21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0, gettext ("the archive '%s' is too large"),
21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   arfname);
21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We only add symbol tables for ELF files.  It makes not much sense
22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng     to add symbols from executables but we do so for compatibility.
22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng     For DSOs and executables we use the dynamic symbol table, for
22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng     relocatable files all the DT_SYMTAB tables.  */
22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (elf_kind (elf) != ELF_K_ELF)
22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Ehdr ehdr_mem;
22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ehdr == NULL)
22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0, gettext ("cannot read ELF header of %s(%s): %s"),
23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   arfname, membername, elf_errmsg (-1));
23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Word symtype;
23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ehdr->e_type == ET_REL)
23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    symtype = SHT_SYMTAB;
23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else if (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN)
23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    symtype = SHT_DYNSYM;
23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* We do not handle that type.  */
23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return;
24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Iterate over all sections.  */
24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *scn = NULL;
24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((scn = elf_nextscn (elf, scn)) != NULL)
24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Get the section header.  */
24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr shdr_mem;
24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr == NULL)
24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (shdr->sh_type != symtype)
25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Data *data = elf_getdata (scn, NULL);
25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (data == NULL)
25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	continue;
25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int nsyms = shdr->sh_size / shdr->sh_entsize;
25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (int ndx = shdr->sh_info; ndx < nsyms; ++ndx)
26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Sym sym_mem;
26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Sym *sym = gelf_getsym (data, ndx, &sym_mem);
26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (sym == NULL)
26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    continue;
26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Ignore undefined symbols.  */
26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (sym->st_shndx == SHN_UNDEF)
26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    continue;
26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Use this symbol.  */
27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const char *symname = elf_strptr (elf, shdr->sh_link, sym->st_name);
27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (symname != NULL)
27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    arlib_add_symref (symname, off);
27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Only relocatable files can have more than one symbol table.  */
27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (ehdr->e_type != ET_REL)
27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
281