Blame libasm/asm_newscn.c

Packit 032894
/* Create new section in output file.
Packit 032894
   Copyright (C) 2002-2011, 2016 Red Hat, Inc.
Packit 032894
   This file is part of elfutils.
Packit 032894
   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
Packit 032894
Packit 032894
   This file is free software; you can redistribute it and/or modify
Packit 032894
   it under the terms of either
Packit 032894
Packit 032894
     * the GNU Lesser General Public License as published by the Free
Packit 032894
       Software Foundation; either version 3 of the License, or (at
Packit 032894
       your option) any later version
Packit 032894
Packit 032894
   or
Packit 032894
Packit 032894
     * the GNU General Public License as published by the Free
Packit 032894
       Software Foundation; either version 2 of the License, or (at
Packit 032894
       your option) any later version
Packit 032894
Packit 032894
   or both in parallel, as here.
Packit 032894
Packit 032894
   elfutils is distributed in the hope that it will be useful, but
Packit 032894
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 032894
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 032894
   General Public License for more details.
Packit 032894
Packit 032894
   You should have received copies of the GNU General Public License and
Packit 032894
   the GNU Lesser General Public License along with this program.  If
Packit 032894
   not, see <http://www.gnu.org/licenses/>.  */
Packit 032894
Packit 032894
#ifdef HAVE_CONFIG_H
Packit 032894
# include <config.h>
Packit 032894
#endif
Packit 032894
Packit 032894
#include <assert.h>
Packit 032894
#include <libintl.h>
Packit 032894
#include <stdlib.h>
Packit 032894
#include <string.h>
Packit 032894
Packit 032894
#include <libasmP.h>
Packit 032894
#include <libelf.h>
Packit 032894
#include <system.h>
Packit 032894
Packit 032894
Packit 032894
/* Memory for the default pattern.  The type uses a flexible array
Packit 032894
   which does work well with a static initializer.  So we play some
Packit 032894
   dirty tricks here.  */
Packit 032894
static const struct
Packit 032894
{
Packit 032894
  struct FillPattern pattern;
Packit 032894
  char zero;
Packit 032894
} xdefault_pattern =
Packit 032894
  {
Packit 032894
    .pattern =
Packit 032894
    {
Packit 032894
      .len = 1
Packit 032894
    },
Packit 032894
    .zero = '\0'
Packit 032894
  };
Packit 032894
const struct FillPattern *__libasm_default_pattern = &xdefault_pattern.pattern;
Packit 032894
Packit 032894
Packit 032894
static AsmScn_t *
Packit 032894
text_newscn (AsmScn_t *result, GElf_Word type, GElf_Xword flags)
Packit 032894
{
Packit 032894
  /* Buffer where we construct the flag string.  */
Packit 032894
  char flagstr[sizeof (GElf_Xword) * 8 + 5];
Packit 032894
  char *wp = flagstr;
Packit 032894
  const char *typestr = "";
Packit 032894
Packit 032894
  /* Only write out the flag string if this is the first time the
Packit 032894
     section is selected.  Some assemblers cannot cope with the
Packit 032894
     .section pseudo-op otherwise.  */
Packit 032894
  wp = stpcpy (wp, ", \"");
Packit 032894
Packit 032894
  if (flags & SHF_WRITE)
Packit 032894
    *wp++ = 'w';
Packit 032894
  if (flags & SHF_ALLOC)
Packit 032894
    *wp++ = 'a';
Packit 032894
  if (flags & SHF_EXECINSTR)
Packit 032894
    *wp++ = 'x';
Packit 032894
  if (flags & SHF_MERGE)
Packit 032894
    *wp++ = 'M';
Packit 032894
  if (flags & SHF_STRINGS)
Packit 032894
    *wp++ = 'S';
Packit 032894
  if (flags & SHF_LINK_ORDER)
Packit 032894
    *wp++ = 'L';
Packit 032894
Packit 032894
  *wp++ = '"';
Packit 032894
Packit 032894
  if (type == SHT_PROGBITS)
Packit 032894
    typestr = ",@progbits";
Packit 032894
  else if (type == SHT_NOBITS)
Packit 032894
    typestr = ",@nobits";
Packit 032894
Packit 032894
  /* Terminate the string.  */
Packit 032894
  *wp = '\0';
Packit 032894
Packit 032894
  fprintf (result->ctx->out.file, "\t.section \"%s\"%s%s\n",
Packit 032894
	   result->name, flagstr, typestr);
Packit 032894
Packit 032894
  return result;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
static AsmScn_t *
Packit 032894
binary_newscn (AsmScn_t *result, GElf_Word type, GElf_Xword flags,
Packit 032894
	       size_t scnname_len)
Packit 032894
{
Packit 032894
  GElf_Shdr shdr_mem;
Packit 032894
  GElf_Shdr *shdr;
Packit 032894
  Elf_Scn *scn;
Packit 032894
Packit 032894
  /* The initial subsection has the number zero.  */
Packit 032894
  result->subsection_id = 0;
Packit 032894
Packit 032894
  /* We start at offset zero.  */
Packit 032894
  result->offset = 0;
Packit 032894
  /* And generic alignment.  */
Packit 032894
  result->max_align = 1;
Packit 032894
Packit 032894
  /* No output yet.  */
Packit 032894
  result->content = NULL;
Packit 032894
Packit 032894
  /* Put the default fill pattern in place.  */
Packit 032894
  result->pattern = (struct FillPattern *) __libasm_default_pattern;
Packit 032894
Packit 032894
  /* There are no subsections so far.  */
Packit 032894
  result->subnext = NULL;
Packit 032894
Packit 032894
  /* Add the name to the section header string table.  */
Packit 032894
  result->data.main.strent = dwelf_strtab_add_len (result->ctx->section_strtab,
Packit 032894
						   result->name, scnname_len);
Packit 032894
  assert (result->data.main.strent != NULL);
Packit 032894
Packit 032894
  /* Create the new ELF section.  */
Packit 032894
  result->data.main.scn = scn = elf_newscn (result->ctx->out.elf);
Packit 032894
  if (scn == NULL)
Packit 032894
    {
Packit 032894
      free (result);
Packit 032894
      __libasm_seterrno (ASM_E_LIBELF);
Packit 032894
      return NULL;
Packit 032894
    }
Packit 032894
Packit 032894
  /* Not part of a section group (yet).  */
Packit 032894
  result->data.main.next_in_group = NULL;
Packit 032894
Packit 032894
  /* Remember the flags.  */
Packit 032894
  shdr = gelf_getshdr (scn, &shdr_mem);
Packit 032894
Packit 032894
  shdr->sh_flags = flags;
Packit 032894
  result->type = shdr->sh_type = type;
Packit 032894
Packit 032894
  (void) gelf_update_shdr (scn, shdr);
Packit 032894
Packit 032894
  return result;
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
AsmScn_t *
Packit 032894
asm_newscn (AsmCtx_t *ctx, const char *scnname, GElf_Word type,
Packit 032894
	    GElf_Xword flags)
Packit 032894
{
Packit 032894
  size_t scnname_len = strlen (scnname) + 1;
Packit 032894
  AsmScn_t *result;
Packit 032894
Packit 032894
  /* If no context is given there might be an earlier error.  */
Packit 032894
  if (ctx == NULL)
Packit 032894
    return NULL;
Packit 032894
Packit 032894
  /* Check whether only flags are set which areselectable by the user.  */
Packit 032894
  if (unlikely ((flags & ~(SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR | SHF_MERGE
Packit 032894
			   | SHF_STRINGS | SHF_LINK_ORDER)) != 0)
Packit 032894
      /* We allow only two section types: data and data without file
Packit 032894
	 representation.  */
Packit 032894
      || (type != SHT_PROGBITS && unlikely (type != SHT_NOBITS)))
Packit 032894
    {
Packit 032894
      __libasm_seterrno (ASM_E_INVALID);
Packit 032894
      return NULL;
Packit 032894
    }
Packit 032894
Packit 032894
  rwlock_wrlock (ctx->lock);
Packit 032894
Packit 032894
  /* This is a new section.  */
Packit 032894
  result = (AsmScn_t *) malloc (sizeof (AsmScn_t) + scnname_len);
Packit 032894
  if (result != NULL)
Packit 032894
    {
Packit 032894
      /* Add the name.  */
Packit 032894
      memcpy (result->name, scnname, scnname_len);
Packit 032894
Packit 032894
      /* Add the reference to the context.  */
Packit 032894
      result->ctx = ctx;
Packit 032894
Packit 032894
      /* Perform operations according to output mode.  */
Packit 032894
      result = (unlikely (ctx->textp)
Packit 032894
		? text_newscn (result, type, flags)
Packit 032894
		: binary_newscn (result, type, flags, scnname_len));
Packit 032894
Packit 032894
      /* If everything went well finally add the new section to the hash
Packit 032894
	 table.  */
Packit 032894
      if (result != NULL)
Packit 032894
	{
Packit 032894
	  result->allnext = ctx->section_list;
Packit 032894
	  ctx->section_list = result;
Packit 032894
	}
Packit 032894
    }
Packit 032894
Packit 032894
  rwlock_unlock (ctx->lock);
Packit 032894
Packit 032894
  return result;
Packit 032894
}
Packit 032894
INTDEF(asm_newscn)