125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Finalize operations on the assembler context, free all resources.
225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Copyright (C) 2002, 2003, 2005 Red Hat, Inc.
325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   This file is part of Red Hat elfutils.
425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is free software; you can redistribute it and/or modify
725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   it under the terms of the GNU General Public License as published by the
825b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Free Software Foundation; version 2 of the License.
925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is distributed in the hope that it will be useful, but
1125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   WITHOUT ANY WARRANTY; without even the implied warranty of
1225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   General Public License for more details.
1425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   You should have received a copy of the GNU General Public License along
1625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   with Red Hat elfutils; if not, write to the Free Software Foundation,
1725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
1825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1925b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is an included package of the Open Invention Network.
2025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   An included package of the Open Invention Network is a package for which
2125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Open Invention Network licensees cross-license their patents.  No patent
2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   license is granted, either expressly or impliedly, by designation as an
2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   included package.  Should you wish to participate in the Open Invention
2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Network licensing program, please visit www.openinventionnetwork.com
2525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   <http://www.openinventionnetwork.com>.  */
2625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
2725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef HAVE_CONFIG_H
2825b3c049e70834cf33790a28643ab058b507b35cBen Cheng# include <config.h>
2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <assert.h>
3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <error.h>
3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <libintl.h>
3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdio.h>
3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdlib.h>
3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <string.h>
3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <unistd.h>
3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/stat.h>
3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <libasmP.h>
4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <libelf.h>
4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <system.h>
4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
4625b3c049e70834cf33790a28643ab058b507b35cBen Chengtext_end (AsmCtx_t *ctx __attribute__ ((unused)))
4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (fclose (ctx->out.file) != 0)
4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      __libasm_seterrno (ASM_E_IOERROR);
5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return -1;
5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
5925b3c049e70834cf33790a28643ab058b507b35cBen Chengbinary_end (AsmCtx_t *ctx)
6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  void *symtab = NULL;
6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct Ebl_Strent *symscn_strent = NULL;
6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct Ebl_Strent *strscn_strent = NULL;
6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct Ebl_Strent *xndxscn_strent = NULL;
6525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Scn *shstrscn;
6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct Ebl_Strent *shstrscn_strent;
6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shstrscnndx;
6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t symscnndx = 0;
6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t strscnndx = 0;
7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t xndxscnndx = 0;
7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data;
7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *shstrtabdata;
7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *strtabdata = NULL;
7425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *xndxdata = NULL;
7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr shdr_mem;
7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Shdr *shdr;
7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Ehdr ehdr_mem;
7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Ehdr *ehdr;
7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  AsmScn_t *asmscn;
8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int result = 0;
8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Iterate over the created sections and compute the offsets of the
8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng     various subsections and fill in the content.  */
8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (asmscn = ctx->section_list; asmscn != NULL; asmscn = asmscn->allnext)
8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if 0
8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Scn *scn = elf_getscn (ctx->out.elf, asmscn->data.main.scnndx);
8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else
8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Scn *scn = asmscn->data.main.scn;
9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      off_t offset = 0;
9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      AsmScn_t *asmsubscn = asmscn;
9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      do
9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  struct AsmData *content = asmsubscn->content;
9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  bool first = true;
9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset = ((offset + asmsubscn->max_align - 1)
10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    & ~(asmsubscn->max_align - 1));
10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Update the offset for this subsection.  This field now
10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     stores the offset of the first by in this subsection.  */
10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  asmsubscn->offset = offset;
10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Note that the content list is circular.  */
10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (content != NULL)
10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    do
10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      {
11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		Elf_Data *newdata = elf_newdata (scn);
11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		if (newdata == NULL)
11325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  {
11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    __libasm_seterrno (ASM_E_LIBELF);
11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    return -1;
11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  }
11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		newdata->d_buf = content->data;
11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		newdata->d_type = ELF_T_BYTE;
12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		newdata->d_size = content->len;
12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		newdata->d_off = offset;
12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		newdata->d_align = first ? asmsubscn->max_align : 1;
12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		offset += content->len;
12525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      }
12625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    while ((content = content->next) != asmsubscn->content);
12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while ((asmsubscn = asmsubscn->subnext) != NULL);
12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Create the symbol table if necessary.  */
13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ctx->nsymbol_tab > 0)
13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Create the symbol table and string table section names.  */
13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      symscn_strent = ebl_strtabadd (ctx->section_strtab, ".symtab", 8);
13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      strscn_strent = ebl_strtabadd (ctx->section_strtab, ".strtab", 8);
13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Create the symbol string table section.  */
14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Scn *strscn = elf_newscn (ctx->out.elf);
14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      strtabdata = elf_newdata (strscn);
14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      shdr = gelf_getshdr (strscn, &shdr_mem);
14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (strtabdata == NULL || shdr == NULL)
14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  __libasm_seterrno (ASM_E_LIBELF);
14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return -1;
14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      strscnndx = elf_ndxscn (strscn);
14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ebl_strtabfinalize (ctx->symbol_strtab, strtabdata);
15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      shdr->sh_type = SHT_STRTAB;
15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (shdr->sh_entsize == 0);
15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      (void) gelf_update_shdr (strscn, shdr);
15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Create the symbol table section.  */
15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Scn *symscn = elf_newscn (ctx->out.elf);
15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      data = elf_newdata (symscn);
16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      shdr = gelf_getshdr (symscn, &shdr_mem);
16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (data == NULL || shdr == NULL)
16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  __libasm_seterrno (ASM_E_LIBELF);
16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return -1;
16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      symscnndx = elf_ndxscn (symscn);
16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We know how many symbols there will be in the symbol table.  */
16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      data->d_size = gelf_fsize (ctx->out.elf, ELF_T_SYM,
17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng				 ctx->nsymbol_tab + 1, EV_CURRENT);
17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      symtab = malloc (data->d_size);
17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (symtab == NULL)
17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return -1;
17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      data->d_buf = symtab;
17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      data->d_type = ELF_T_SYM;
17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      data->d_off = 0;
17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Clear the first entry.  */
17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Sym syment;
18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      memset (&syment, '\0', sizeof (syment));
18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      (void) gelf_update_sym (data, 0, &syment);
18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Iterate over the symbol table.  */
18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      void *runp = NULL;
18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int ptr_local = 1;	/* Start with index 1; zero remains unused.  */
18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      int ptr_nonlocal = ctx->nsymbol_tab;
18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      uint32_t *xshndx = NULL;
18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      AsmSym_t *sym;
18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while ((sym = asm_symbol_tab_iterate (&ctx->symbol_tab, &runp)) != NULL)
19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	if (asm_emit_symbol_p (ebl_string (sym->strent)))
19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  {
19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    assert (ptr_local <= ptr_nonlocal);
19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    syment.st_name = ebl_strtaboffset (sym->strent);
19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    syment.st_info = GELF_ST_INFO (sym->binding, sym->type);
19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    syment.st_other = 0;
19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    syment.st_value = sym->scn->offset + sym->offset;
19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    syment.st_size = sym->size;
19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* Add local symbols at the beginning, the other from
20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       the end.  */
20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    int ptr = sym->binding == STB_LOCAL ? ptr_local++ : ptr_nonlocal--;
20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* Determine the section index.  We have to handle the
20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       overflow correctly.  */
20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    Elf_Scn *scn = (sym->scn->subsection_id == 0
20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    ? sym->scn->data.main.scn
20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    : sym->scn->data.up->data.main.scn);
20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    Elf32_Word ndx;
21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    if (unlikely (scn == ASM_ABS_SCN))
21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ndx = SHN_ABS;
21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    else if (unlikely (scn == ASM_COM_SCN))
21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ndx = SHN_COMMON;
21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    else if (unlikely ((ndx = elf_ndxscn (scn)) >= SHN_LORESERVE))
21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      {
21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		if (unlikely (xshndx == NULL))
21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  {
21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    /* The extended section index section does not yet
22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       exist.  */
22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    Elf_Scn *xndxscn;
22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    xndxscn = elf_newscn (ctx->out.elf);
22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    xndxdata = elf_newdata (xndxscn);
22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    shdr = gelf_getshdr (xndxscn, &shdr_mem);
22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    if (xndxdata == NULL || shdr == NULL)
22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      {
22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			__libasm_seterrno (ASM_E_LIBELF);
22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			return -1;
23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      }
23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    xndxscnndx = elf_ndxscn (xndxscn);
23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    shdr->sh_type = SHT_SYMTAB_SHNDX;
23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    shdr->sh_entsize = sizeof (Elf32_Word);
23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    shdr->sh_addralign = sizeof (Elf32_Word);
23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    shdr->sh_link = symscnndx;
23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    (void) gelf_update_shdr (xndxscn, shdr);
23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    xndxscn_strent = ebl_strtabadd (ctx->section_strtab,
24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng						    ".symtab_shndx", 14);
24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    /* Note that using 'elf32_fsize' instead of
24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       'gelf_fsize' here is correct.  */
24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    xndxdata->d_size = elf32_fsize (ELF_T_WORD,
24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng						    ctx->nsymbol_tab + 1,
24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng						    EV_CURRENT);
24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    xshndx = xndxdata->d_buf = calloc (1, xndxdata->d_size);
24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    if (xshndx == NULL)
25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      return -1;
25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    /* Using ELF_T_WORD here relies on the fact that the
25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       32- and 64-bit types are the same size.  */
25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    xndxdata->d_type = ELF_T_WORD;
25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    xndxdata->d_off = 0;
25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  }
25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		/* Store the real section index in the extended setion
25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   index table.  */
25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		assert ((size_t) ptr < ctx->nsymbol_tab + 1);
26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		xshndx[ptr] = ndx;
26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		/* And signal that this happened.  */
26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		ndx = SHN_XINDEX;
26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      }
26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    syment.st_shndx = ndx;
26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* Remember where we put the symbol.  */
26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    sym->symidx = ptr;
26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    (void) gelf_update_sym (data, ptr, &syment);
27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  }
27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (ptr_local == ptr_nonlocal + 1);
27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      shdr->sh_type = SHT_SYMTAB;
27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      shdr->sh_link = strscnndx;
27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      shdr->sh_info = ptr_local;
27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      shdr->sh_entsize = gelf_fsize (ctx->out.elf, ELF_T_SYM, 1, EV_CURRENT);
27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      shdr->sh_addralign = gelf_fsize (ctx->out.elf, ELF_T_ADDR, 1,
28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng				       EV_CURRENT);
28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      (void) gelf_update_shdr (symscn, shdr);
28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Create the section header string table section and fill in the
28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng     references in the section headers.  */
28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  shstrscn = elf_newscn (ctx->out.elf);
28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  shstrtabdata = elf_newdata (shstrscn);
29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  shdr = gelf_getshdr (shstrscn, &shdr_mem);
29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (shstrscn == NULL || shstrtabdata == NULL || shdr == NULL)
29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      __libasm_seterrno (ASM_E_LIBELF);
29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return -1;
29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Add the name of the section header string table.  */
29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  shstrscn_strent = ebl_strtabadd (ctx->section_strtab, ".shstrtab", 10);
30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ebl_strtabfinalize (ctx->section_strtab, shstrtabdata);
30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  shdr->sh_type = SHT_STRTAB;
30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (shdr->sh_entsize == 0);
30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  shdr->sh_name = ebl_strtaboffset (shstrscn_strent);
30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) gelf_update_shdr (shstrscn, shdr);
30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Create the section groups.  */
31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ctx->groups != NULL)
31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      AsmScnGrp_t *runp = ctx->groups->next;
31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      do
31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
31725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf_Scn *scn;
31825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf32_Word *grpdata;
31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
32025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  scn = runp->scn;
32125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  assert (scn != NULL);
32225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr = gelf_getshdr (scn, &shdr_mem);
32325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  assert (shdr != NULL);
32425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
32525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data = elf_newdata (scn);
32625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (data == NULL)
32725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
32825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      __libasm_seterrno (ASM_E_LIBELF);
32925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      return -1;
33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* It is correct to use 'elf32_fsize' instead of 'gelf_fsize'
33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     here.  */
33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data->d_size = elf32_fsize (ELF_T_WORD, runp->nmembers + 1,
33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      EV_CURRENT);
33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  grpdata = data->d_buf = malloc (data->d_size);
33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (grpdata == NULL)
33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return -1;
33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data->d_type = ELF_T_WORD;
34025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data->d_off = 0;
34125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  data->d_align = elf32_fsize (ELF_T_WORD, 1, EV_CURRENT);
34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* The first word of the section is filled with the flag word.  */
34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  *grpdata++ = runp->flags;
34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (runp->members != NULL)
34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
34825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      AsmScn_t *member = runp->members->data.main.next_in_group;
34925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      do
35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
35225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Only sections, not subsections, can be registered
35325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     as member of a group.  The subsections get
35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     automatically included.  */
35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  assert (member->subsection_id == 0);
35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  *grpdata++ = elf_ndxscn (member->data.main.scn);
35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      while ((member = member->data.main.next_in_group)
36025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     != runp->members->data.main.next_in_group);
36125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
36225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
36325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Construct the section header.  */
36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr->sh_name = ebl_strtaboffset (runp->strent);
36525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr->sh_type = SHT_GROUP;
36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr->sh_flags = 0;
36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr->sh_link = symscnndx;
36825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* If the user did not specify a signature we use the initial
36925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     empty symbol in the symbol table as the signature.  */
37025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr->sh_info = (runp->signature != NULL
37125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   ? runp->signature->symidx : 0);
37225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
37325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (void) gelf_update_shdr (scn, shdr);
37425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
37525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while ((runp = runp->next) != ctx->groups->next);
37625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
37725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
37825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
37925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Add the name to the symbol section.  */
38025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (symscnndx != 0))
38125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
38225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Scn *scn = elf_getscn (ctx->out.elf, symscnndx);
38325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
38425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      shdr = gelf_getshdr (scn, &shdr_mem);
38525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
38625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      shdr->sh_name = ebl_strtaboffset (symscn_strent);
38725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
38825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      (void) gelf_update_shdr (scn, shdr);
38925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
39025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
39125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Add the name to the string section.  */
39225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (strscnndx != 0);
39325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      scn = elf_getscn (ctx->out.elf, strscnndx);
39425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
39525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      shdr = gelf_getshdr (scn, &shdr_mem);
39625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
39725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      shdr->sh_name = ebl_strtaboffset (strscn_strent);
39825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
39925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      (void) gelf_update_shdr (scn, shdr);
40025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
40125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
40225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Add the name to the extended symbol index section.  */
40325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (xndxscnndx != 0)
40425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
40525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  scn = elf_getscn (ctx->out.elf, xndxscnndx);
40625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
40725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr = gelf_getshdr (scn, &shdr_mem);
40825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
40925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  shdr->sh_name = ebl_strtaboffset (xndxscn_strent);
41025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
41125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (void) gelf_update_shdr (scn, shdr);
41225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
41325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
41425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
41525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
41625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Iterate over the created sections and fill in the names.  */
41725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (asmscn = ctx->section_list; asmscn != NULL; asmscn = asmscn->allnext)
41825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
41925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      shdr = gelf_getshdr (asmscn->data.main.scn, &shdr_mem);
42025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* This better should not fail.  */
42125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (shdr != NULL);
42225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
42325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      shdr->sh_name = ebl_strtaboffset (asmscn->data.main.strent);
42425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
42525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We now know the maximum alignment.  */
42625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      shdr->sh_addralign = asmscn->max_align;
42725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
42825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      (void) gelf_update_shdr (asmscn->data.main.scn, shdr);
42925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
43025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
43125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Put the reference to the section header string table in the ELF
43225b3c049e70834cf33790a28643ab058b507b35cBen Cheng     header.  */
43325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ehdr = gelf_getehdr (ctx->out.elf, &ehdr_mem);
43425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (ehdr != NULL);
43525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
43625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  shstrscnndx = elf_ndxscn (shstrscn);
43725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (shstrscnndx > SHN_HIRESERVE)
43825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      || unlikely (shstrscnndx == SHN_XINDEX))
43925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
44025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* The index of the section header string sectio is too large.  */
44125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Scn *scn = elf_getscn (ctx->out.elf, 0);
44225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
44325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Get the header for the zeroth section.  */
44425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      shdr = gelf_getshdr (scn, &shdr_mem);
44525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* This better does not fail.  */
44625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (shdr != NULL);
44725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
44825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* The sh_link field of the zeroth section header contains the value.  */
44925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      shdr->sh_link = shstrscnndx;
45025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
45125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      (void) gelf_update_shdr (scn, shdr);
45225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
45325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* This is the sign for the overflow.  */
45425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ehdr->e_shstrndx = SHN_XINDEX;
45525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
45625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
45725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    ehdr->e_shstrndx = elf_ndxscn (shstrscn);
45825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
45925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  gelf_update_ehdr (ctx->out.elf, ehdr);
46025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
46125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Write out the ELF file.  */
46225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_update (ctx->out.elf, ELF_C_WRITE_MMAP)) < 0)
46325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
46425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      __libasm_seterrno (ASM_E_LIBELF);
46525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result = -1;
46625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
46725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
46825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We do not need the section header and symbol string tables anymore.  */
46925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (shstrtabdata->d_buf);
47025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (strtabdata != NULL)
47125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    free (strtabdata->d_buf);
47225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We might have allocated the extended symbol table index.  */
47325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (xndxdata != NULL)
47425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    free (xndxdata->d_buf);
47525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
47625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Free section groups memory.  */
47725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  AsmScnGrp_t *scngrp = ctx->groups;
47825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (scngrp != NULL)
47925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    do
48025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      free (elf_getdata (scngrp->scn, NULL)->d_buf);
48125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    while ((scngrp = scngrp->next) != ctx->groups);
48225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
48325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Finalize the ELF handling.  */
48425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_end (ctx->out.elf)) != 0)
48525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
48625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      __libasm_seterrno (ASM_E_LIBELF);
48725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result = -1;
48825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
48925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
49025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Free the temporary resources.  */
49125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (symtab);
49225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
49325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return result;
49425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
49525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
49625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
49725b3c049e70834cf33790a28643ab058b507b35cBen Chengint
49825b3c049e70834cf33790a28643ab058b507b35cBen Chengasm_end (ctx)
49925b3c049e70834cf33790a28643ab058b507b35cBen Cheng     AsmCtx_t *ctx;
50025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
50125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int result;
50225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
50325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ctx == NULL)
50425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* Something went wrong earlier.  */
50525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
50625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
50725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  result = unlikely (ctx->textp) ? text_end (ctx) : binary_end (ctx);
50825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (result != 0)
50925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return result;
51025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
51125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Make the new file globally readable and user/group-writable.  */
51225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (fchmod (ctx->fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH) != 0)
51325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
51425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      __libasm_seterrno (ASM_E_CANNOT_CHMOD);
51525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return -1;
51625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
51725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
51825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Rename output file.  */
51925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (rename (ctx->tmp_fname, ctx->fname) != 0)
52025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
52125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      __libasm_seterrno (ASM_E_CANNOT_RENAME);
52225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return -1;
52325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
52425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
52525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Free the resources.  */
52625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  __libasm_finictx (ctx);
52725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
52825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
52925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
53025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
53125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
53225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
53325b3c049e70834cf33790a28643ab058b507b35cBen Chengfree_section (AsmScn_t *scnp)
53425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
53525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  void *oldp;
53625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
53725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (scnp->subnext != NULL)
53825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    free_section (scnp->subnext);
53925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
54025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct AsmData *data = scnp->content;
54125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (data != NULL)
54225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    do
54325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
54425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	oldp = data;
54525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	data = data->next;
54625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	free (oldp);
54725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
54825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    while (oldp != scnp->content);
54925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
55025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (scnp);
55125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
55225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
55325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
55425b3c049e70834cf33790a28643ab058b507b35cBen Chengvoid
55525b3c049e70834cf33790a28643ab058b507b35cBen Cheng__libasm_finictx (ctx)
55625b3c049e70834cf33790a28643ab058b507b35cBen Cheng     AsmCtx_t *ctx;
55725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
55825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Iterate through section table and free individual entries.  */
55925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  AsmScn_t *scn = ctx->section_list;
56025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (scn != NULL)
56125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
56225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      AsmScn_t *oldp = scn;
56325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      scn = scn->allnext;
56425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      free_section (oldp);
56525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
56625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
56725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Free the resources of the symbol table.  */
56825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  void *runp = NULL;
56925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  AsmSym_t *sym;
57025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((sym = asm_symbol_tab_iterate (&ctx->symbol_tab, &runp)) != NULL)
57125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    free (sym);
57225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  asm_symbol_tab_free (&ctx->symbol_tab);
57325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
57425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
57525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Free section groups.  */
57625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  AsmScnGrp_t *scngrp = ctx->groups;
57725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (scngrp != NULL)
57825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    do
57925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
58025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	AsmScnGrp_t *oldp = scngrp;
58125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
58225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	scngrp = scngrp->next;
58325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	free (oldp);
58425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
58525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    while (scngrp != ctx->groups);
58625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
58725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
58825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (ctx->textp))
58925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
59025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Close the stream.  */
59125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      fclose (ctx->out.file);
59225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
59325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
59425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
59525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Close the output file.  */
59625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* XXX We should test for errors here but what would we do if we'd
59725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 find any.  */
59825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      (void) close (ctx->fd);
59925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
60025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* And the string tables.  */
60125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ebl_strtabfree (ctx->section_strtab);
60225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ebl_strtabfree (ctx->symbol_strtab);
60325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
60425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
60525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Initialize the lock.  */
60625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  rwlock_fini (ctx->lock);
60725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
60825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Finally free the data structure.   */
60925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  free (ctx);
61025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
611